master 9712d9721d05 cached
88 files
277.4 KB
87.1k tokens
1 requests
Download .txt
Showing preview only (301K chars total). Download the full file or copy to clipboard to get everything.
Repository: nrinaudo/scala-best-practices
Branch: master
Commit: 9712d9721d05
Files: 88
Total size: 277.4 KB

Directory structure:
gitextract_y_x3cf17/

├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.sbt
├── project/
│   ├── MdocSitePlugin.scala
│   ├── build.properties
│   └── plugins.sbt
└── src/
    ├── main/
    │   └── mdoc/
    │       ├── _adts/
    │       │   ├── data_constructors_in_companion_object.md
    │       │   ├── enumerations_as_adt.md
    │       │   ├── errors_extend_exception.md
    │       │   ├── final_case_objects.md
    │       │   ├── index.md
    │       │   └── product_with_serializable.md
    │       ├── _binary_compat/
    │       │   ├── abstract_over_trait.md
    │       │   ├── explicit_type_annotations.md
    │       │   └── index.md
    │       ├── _definitions/
    │       │   ├── adt.md
    │       │   ├── binary_compatibility.md
    │       │   ├── final.md
    │       │   ├── implicit_scope.md
    │       │   ├── paren-less.md
    │       │   ├── recursion.md
    │       │   ├── reference_equality.md
    │       │   ├── referential_transparency.md
    │       │   ├── sealed.md
    │       │   ├── tail_recursion.md
    │       │   ├── total_function.md
    │       │   └── type_class.md
    │       ├── _oop/
    │       │   ├── abstract_fields_as_defs.md
    │       │   ├── always_override.md
    │       │   └── index.md
    │       ├── _partial_functions/
    │       │   ├── either_projection_get.md
    │       │   ├── index.md
    │       │   ├── option_get.md
    │       │   ├── traversable_head.md
    │       │   ├── traversable_init.md
    │       │   ├── traversable_last.md
    │       │   ├── traversable_reduce.md
    │       │   ├── traversable_tail.md
    │       │   └── try_get.md
    │       ├── _referential_transparency/
    │       │   ├── avoid_mutability.md
    │       │   ├── avoid_return.md
    │       │   ├── avoid_throwing_exceptions.md
    │       │   └── index.md
    │       ├── _tricky_behaviours/
    │       │   ├── final_case_classes.md
    │       │   ├── future_in_comprehensions.md
    │       │   ├── implicit_shadowing.md
    │       │   ├── index.md
    │       │   ├── leaky_sealed_types.md
    │       │   ├── string_concatenation.md
    │       │   ├── type_implicits.md
    │       │   └── unicode_operators.md
    │       ├── _unsafe/
    │       │   ├── array_comparison.md
    │       │   ├── avoid_null.md
    │       │   ├── checking_empty_collection.md
    │       │   ├── custom_extractors.md
    │       │   ├── implicit_conversions.md
    │       │   ├── index.md
    │       │   ├── recursion.md
    │       │   ├── structural_types.md
    │       │   └── tail_recursion.md
    │       ├── _warming_up/
    │       │   ├── checking_for_nan.md
    │       │   ├── checking_for_odd.md
    │       │   ├── index.md
    │       │   └── numeric_literals.md
    │       └── index.md
    └── site/
        ├── _config.yml
        ├── _includes/
        │   ├── footer.html
        │   ├── header.html
        │   ├── linters.html
        │   └── toc.html
        ├── _layouts/
        │   ├── article.html
        │   ├── compress.html
        │   ├── definition.html
        │   ├── index.html
        │   └── section.html
        ├── css/
        │   ├── fira_code/
        │   │   └── fira_code.css
        │   ├── fontawesome/
        │   │   └── font-awesome.css
        │   ├── inter/
        │   │   └── inter.css
        │   └── styles.css
        └── fonts/
            ├── fira/
            │   ├── LICENSE
            │   ├── fira.css
            │   └── otf/
            │       ├── FiraMono-Bold.otf
            │       ├── FiraMono-Medium.otf
            │       └── FiraMono-Regular.otf
            └── fontawesome/
                ├── FontAwesome.otf
                └── font-awesome.css

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.class
*.log

# sbt specific
.cache/
.history/
.lib/
dist/*
target/
lib_managed/
src_managed/
project/boot/
project/plugins/project/

# Scala-IDE specific
.scala_dependencies
.worksheet

# Ensime
.ensime
.ensime_cache

# Intellij
.idea/
*.iml
*.iws

# Mac
.DS_Store

# Auto-generated files
.scalafmt.conf
scalastyle-config.xml


================================================
FILE: .travis.yml
================================================
language: scala
dist: trusty
sudo: false
cache:
  directories:
    - $HOME/.ivy2/cache
    - $HOME/.sbt/boot/
    - $HOME/.cache/coursier
before_cache:
  # Tricks to avoid unnecessary cache updates
  - find $HOME/.ivy2 -name "ivydata-*.properties" -delete
  - find $HOME/.sbt -name "*.lock" -delete
scala:
  - 2.12.8
jdk:
  - oraclejdk8
script:
  - sbt makeSite


================================================
FILE: LICENSE
================================================
Attribution 4.0 International

=======================================================================

Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.

Using Creative Commons Public Licenses

Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.

     Considerations for licensors: Our public licenses are
     intended for use by those authorized to give the public
     permission to use material in ways otherwise restricted by
     copyright and certain other rights. Our licenses are
     irrevocable. Licensors should read and understand the terms
     and conditions of the license they choose before applying it.
     Licensors should also secure all rights necessary before
     applying our licenses so that the public can reuse the
     material as expected. Licensors should clearly mark any
     material not subject to the license. This includes other CC-
     licensed material, or material used under an exception or
     limitation to copyright. More considerations for licensors:
	wiki.creativecommons.org/Considerations_for_licensors

     Considerations for the public: By using one of our public
     licenses, a licensor grants the public permission to use the
     licensed material under specified terms and conditions. If
     the licensor's permission is not necessary for any reason--for
     example, because of any applicable exception or limitation to
     copyright--then that use is not regulated by the license. Our
     licenses grant only permissions under copyright and certain
     other rights that a licensor has authority to grant. Use of
     the licensed material may still be restricted for other
     reasons, including because others have copyright or other
     rights in the material. A licensor may make special requests,
     such as asking that all changes be marked or described.
     Although not required by our licenses, you are encouraged to
     respect those requests where reasonable. More considerations
     for the public:
	wiki.creativecommons.org/Considerations_for_licensees

=======================================================================

Creative Commons Attribution 4.0 International Public License

By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.


Section 1 -- Definitions.

  a. Adapted Material means material subject to Copyright and Similar
     Rights that is derived from or based upon the Licensed Material
     and in which the Licensed Material is translated, altered,
     arranged, transformed, or otherwise modified in a manner requiring
     permission under the Copyright and Similar Rights held by the
     Licensor. For purposes of this Public License, where the Licensed
     Material is a musical work, performance, or sound recording,
     Adapted Material is always produced where the Licensed Material is
     synched in timed relation with a moving image.

  b. Adapter's License means the license You apply to Your Copyright
     and Similar Rights in Your contributions to Adapted Material in
     accordance with the terms and conditions of this Public License.

  c. Copyright and Similar Rights means copyright and/or similar rights
     closely related to copyright including, without limitation,
     performance, broadcast, sound recording, and Sui Generis Database
     Rights, without regard to how the rights are labeled or
     categorized. For purposes of this Public License, the rights
     specified in Section 2(b)(1)-(2) are not Copyright and Similar
     Rights.

  d. Effective Technological Measures means those measures that, in the
     absence of proper authority, may not be circumvented under laws
     fulfilling obligations under Article 11 of the WIPO Copyright
     Treaty adopted on December 20, 1996, and/or similar international
     agreements.

  e. Exceptions and Limitations means fair use, fair dealing, and/or
     any other exception or limitation to Copyright and Similar Rights
     that applies to Your use of the Licensed Material.

  f. Licensed Material means the artistic or literary work, database,
     or other material to which the Licensor applied this Public
     License.

  g. Licensed Rights means the rights granted to You subject to the
     terms and conditions of this Public License, which are limited to
     all Copyright and Similar Rights that apply to Your use of the
     Licensed Material and that the Licensor has authority to license.

  h. Licensor means the individual(s) or entity(ies) granting rights
     under this Public License.

  i. Share means to provide material to the public by any means or
     process that requires permission under the Licensed Rights, such
     as reproduction, public display, public performance, distribution,
     dissemination, communication, or importation, and to make material
     available to the public including in ways that members of the
     public may access the material from a place and at a time
     individually chosen by them.

  j. Sui Generis Database Rights means rights other than copyright
     resulting from Directive 96/9/EC of the European Parliament and of
     the Council of 11 March 1996 on the legal protection of databases,
     as amended and/or succeeded, as well as other essentially
     equivalent rights anywhere in the world.

  k. You means the individual or entity exercising the Licensed Rights
     under this Public License. Your has a corresponding meaning.


Section 2 -- Scope.

  a. License grant.

       1. Subject to the terms and conditions of this Public License,
          the Licensor hereby grants You a worldwide, royalty-free,
          non-sublicensable, non-exclusive, irrevocable license to
          exercise the Licensed Rights in the Licensed Material to:

            a. reproduce and Share the Licensed Material, in whole or
               in part; and

            b. produce, reproduce, and Share Adapted Material.

       2. Exceptions and Limitations. For the avoidance of doubt, where
          Exceptions and Limitations apply to Your use, this Public
          License does not apply, and You do not need to comply with
          its terms and conditions.

       3. Term. The term of this Public License is specified in Section
          6(a).

       4. Media and formats; technical modifications allowed. The
          Licensor authorizes You to exercise the Licensed Rights in
          all media and formats whether now known or hereafter created,
          and to make technical modifications necessary to do so. The
          Licensor waives and/or agrees not to assert any right or
          authority to forbid You from making technical modifications
          necessary to exercise the Licensed Rights, including
          technical modifications necessary to circumvent Effective
          Technological Measures. For purposes of this Public License,
          simply making modifications authorized by this Section 2(a)
          (4) never produces Adapted Material.

       5. Downstream recipients.

            a. Offer from the Licensor -- Licensed Material. Every
               recipient of the Licensed Material automatically
               receives an offer from the Licensor to exercise the
               Licensed Rights under the terms and conditions of this
               Public License.

            b. No downstream restrictions. You may not offer or impose
               any additional or different terms or conditions on, or
               apply any Effective Technological Measures to, the
               Licensed Material if doing so restricts exercise of the
               Licensed Rights by any recipient of the Licensed
               Material.

       6. No endorsement. Nothing in this Public License constitutes or
          may be construed as permission to assert or imply that You
          are, or that Your use of the Licensed Material is, connected
          with, or sponsored, endorsed, or granted official status by,
          the Licensor or others designated to receive attribution as
          provided in Section 3(a)(1)(A)(i).

  b. Other rights.

       1. Moral rights, such as the right of integrity, are not
          licensed under this Public License, nor are publicity,
          privacy, and/or other similar personality rights; however, to
          the extent possible, the Licensor waives and/or agrees not to
          assert any such rights held by the Licensor to the limited
          extent necessary to allow You to exercise the Licensed
          Rights, but not otherwise.

       2. Patent and trademark rights are not licensed under this
          Public License.

       3. To the extent possible, the Licensor waives any right to
          collect royalties from You for the exercise of the Licensed
          Rights, whether directly or through a collecting society
          under any voluntary or waivable statutory or compulsory
          licensing scheme. In all other cases the Licensor expressly
          reserves any right to collect such royalties.


Section 3 -- License Conditions.

Your exercise of the Licensed Rights is expressly made subject to the
following conditions.

  a. Attribution.

       1. If You Share the Licensed Material (including in modified
          form), You must:

            a. retain the following if it is supplied by the Licensor
               with the Licensed Material:

                 i. identification of the creator(s) of the Licensed
                    Material and any others designated to receive
                    attribution, in any reasonable manner requested by
                    the Licensor (including by pseudonym if
                    designated);

                ii. a copyright notice;

               iii. a notice that refers to this Public License;

                iv. a notice that refers to the disclaimer of
                    warranties;

                 v. a URI or hyperlink to the Licensed Material to the
                    extent reasonably practicable;

            b. indicate if You modified the Licensed Material and
               retain an indication of any previous modifications; and

            c. indicate the Licensed Material is licensed under this
               Public License, and include the text of, or the URI or
               hyperlink to, this Public License.

       2. You may satisfy the conditions in Section 3(a)(1) in any
          reasonable manner based on the medium, means, and context in
          which You Share the Licensed Material. For example, it may be
          reasonable to satisfy the conditions by providing a URI or
          hyperlink to a resource that includes the required
          information.

       3. If requested by the Licensor, You must remove any of the
          information required by Section 3(a)(1)(A) to the extent
          reasonably practicable.

       4. If You Share Adapted Material You produce, the Adapter's
          License You apply must not prevent recipients of the Adapted
          Material from complying with this Public License.


Section 4 -- Sui Generis Database Rights.

Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:

  a. for the avoidance of doubt, Section 2(a)(1) grants You the right
     to extract, reuse, reproduce, and Share all or a substantial
     portion of the contents of the database;

  b. if You include all or a substantial portion of the database
     contents in a database in which You have Sui Generis Database
     Rights, then the database in which You have Sui Generis Database
     Rights (but not its individual contents) is Adapted Material; and

  c. You must comply with the conditions in Section 3(a) if You Share
     all or a substantial portion of the contents of the database.

For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.


Section 5 -- Disclaimer of Warranties and Limitation of Liability.

  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.

  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.

  c. The disclaimer of warranties and limitation of liability provided
     above shall be interpreted in a manner that, to the extent
     possible, most closely approximates an absolute disclaimer and
     waiver of all liability.


Section 6 -- Term and Termination.

  a. This Public License applies for the term of the Copyright and
     Similar Rights licensed here. However, if You fail to comply with
     this Public License, then Your rights under this Public License
     terminate automatically.

  b. Where Your right to use the Licensed Material has terminated under
     Section 6(a), it reinstates:

       1. automatically as of the date the violation is cured, provided
          it is cured within 30 days of Your discovery of the
          violation; or

       2. upon express reinstatement by the Licensor.

     For the avoidance of doubt, this Section 6(b) does not affect any
     right the Licensor may have to seek remedies for Your violations
     of this Public License.

  c. For the avoidance of doubt, the Licensor may also offer the
     Licensed Material under separate terms or conditions or stop
     distributing the Licensed Material at any time; however, doing so
     will not terminate this Public License.

  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
     License.


Section 7 -- Other Terms and Conditions.

  a. The Licensor shall not be bound by any additional or different
     terms or conditions communicated by You unless expressly agreed.

  b. Any arrangements, understandings, or agreements regarding the
     Licensed Material not stated herein are separate from and
     independent of the terms and conditions of this Public License.


Section 8 -- Interpretation.

  a. For the avoidance of doubt, this Public License does not, and
     shall not be interpreted to, reduce, limit, restrict, or impose
     conditions on any use of the Licensed Material that could lawfully
     be made without permission under this Public License.

  b. To the extent possible, if any provision of this Public License is
     deemed unenforceable, it shall be automatically reformed to the
     minimum extent necessary to make it enforceable. If the provision
     cannot be reformed, it shall be severed from this Public License
     without affecting the enforceability of the remaining terms and
     conditions.

  c. No term or condition of this Public License will be waived and no
     failure to comply consented to unless expressly agreed to by the
     Licensor.

  d. Nothing in this Public License constitutes or may be interpreted
     as a limitation upon, or waiver of, any privileges and immunities
     that apply to the Licensor or You, including from the legal
     processes of any jurisdiction or authority.


=======================================================================

Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.

Creative Commons may be contacted at creativecommons.org.


================================================
FILE: README.md
================================================
# Building the site

## Required tools

The following tools are needed to build the site:
* [sbt], to compile and assemble all examples
* [jekyll], to turn the output into a static site

## Steps

You first need to run all pages through the amazing [mdoc](https://github.com/scalameta/mdoc) to make sure all examples are valid:

```shell
sbt makeSite
```

This will generate [jekyll] sources in `./target/site`. For local development / browsing, the simplest thing to do is to run the following from `./target/site`:

```shell
jekyll serve --watch -c _config.yml --baseurl ""
```

This will make the entire site available on `http://localhost:4000`.

[jekyll]:https://jekyllrb.com/
[sbt]:https://www.scala-sbt.org/


================================================
FILE: build.sbt
================================================
enablePlugins(MdocSitePlugin, GhpagesPlugin)

scalaVersion              :=  "2.12.8"
scalacOptions             ++= Seq("-feature", "-language:implicitConversions", "-language:reflectiveCalls")
mdocIn                    :=  (sourceDirectory in Compile).value / "mdoc"
mdocExtraArguments        +=  "--no-link-hygiene"
includeFilter in makeSite :=  "*.yml" | "*.md" | "*.html" | "*.css" | "*.png" | "*.jpg" | "*.gif" | "*.js" | "*.eot" | "*.svg" | "*.ttf" | "*.woff" | "*.woff2" | "*.otf"
git.remoteRepo            :=  "git@github.com:nrinaudo/scala-best-practices.git"
ghpagesNoJekyll           :=  false


================================================
FILE: project/MdocSitePlugin.scala
================================================
import com.typesafe.sbt.site.SitePlugin.autoImport._
import mdoc.MdocPlugin, MdocPlugin.autoImport._
import sbt._, Keys._
import sbt.plugins.{JvmPlugin, SbtPlugin}

/** Provides glue to integrate mdoc with sbt-site. */
object MdocSitePlugin extends AutoPlugin {
  override def trigger = allRequirements

  override def requires = JvmPlugin && MdocPlugin

  object autoImport {
    val mdocSite    = taskKey[Seq[(File, String)]]("create mdoc documentation in a way that lets sbt-site grab it")
    val mdocSiteOut = settingKey[String]("name of the directory in which sbt-site will store mdoc documentation")
  }

  import autoImport._

  override def projectSettings: Seq[Setting[_]] = Seq(
    mdocSite := {
      mdoc.toTask(" ").value
      val out = mdocOut.value
      for {
        (file, name) <- out ** AllPassFilter --- out pair Path.relativeTo(out)
      } yield file -> name
    },
    mdocSiteOut := "./",
    addMappingsToSiteDir(mdocSite, mdocSiteOut)
  )
}


================================================
FILE: project/build.properties
================================================
sbt.version=1.2.6


================================================
FILE: project/plugins.sbt
================================================
addSbtPlugin("org.scalameta"    % "sbt-mdoc"    % "1.2.7")
addSbtPlugin("com.typesafe.sbt" % "sbt-site"    % "1.3.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.2")


================================================
FILE: src/main/mdoc/_adts/data_constructors_in_companion_object.md
================================================
---
title: Declare ADT data constructors in the companion object
layout: article
---

> When writing the various data constructors of an [ADT], put them in the companion object of the root type rather than at the top level.

For example, prefer:

```scala mdoc
sealed abstract class Option[+A] extends Product with Serializable

object Option {
  final case class Some[A](value: A) extends Option[A]
  final case object None extends Option[Nothing]
}
```

To:

```scala mdoc:reset
sealed abstract class Option[+A] extends Product with Serializable

final case class Some[A](value: A) extends Option[A]
final case object None extends Option[Nothing]
```

Yes, I'm aware that this example contradicts the Scala stdlib - that's on purpose. I have [Martin Odersky](https://twitter.com/odersky) on record for recommending exactly the approach that [`Option`] did not take.

# Reason

Putting data constructors in the companion object can be locally made to behave as if they'd been declared at the top level: just import them in.

```scala mdoc
sealed abstract class Foo extends Product with Serializable

object Foo {
  final case object Bar extends Foo
  final case object Baz extends Foo
}

// This brings Bar and Baz in the local scope, exactly as if
// they'd been declared at the top level.
import Foo._

Bar
```

It's however impossible to get top level data constructors to behave as if they'd been declared in the companion object. It's possible to hide or rename them, but this requires one instruction per data constructor, which is verbose and doesn't really scale with large [ADTs][ADT]:

```scala mdoc:reset
object root {
  sealed abstract class Foo extends Product with Serializable

  final case object Bar extends Foo
  final case object Baz extends Foo
}

// This renames Bar to FooBar and imports Foo and Baz into the
// local scope.
import root.{Bar => FooBar, _}

FooBar
```

And while you might argue that you'd rarely need to do that, names are a surprisingly scarce resource. You *will* eventually get in naming conflicts - how many times have I written error types that conflicted with [`Failure`]? This rule helps minimise such conflicts by namespacing all data constructors.

[`Option`]:https://www.scala-lang.org/api/2.12.8/scala/Option.html
[`Failure`]:https://www.scala-lang.org/api/2.12.8/scala/util/Failure.html
[ADT]:../definitions/adt.html


================================================
FILE: src/main/mdoc/_adts/enumerations_as_adt.md
================================================
---
title: Use ADTs to implement enumerations
layout: article
linters:
  - name: wartremover
    rules:
      - name: Enumeration
        url:  http://www.wartremover.org/doc/warts.html#enumeration
---

> When you need to implement an enumeration, use an [ADT], not [`Enumeration`].

# Reason

[`Enumeration`] suffers from a major flaw: exhaustivity is not checked in pattern matches.

For example:

```scala mdoc
object Status extends Enumeration {
  val Ok, Nok = Value
}

def foo(w: Status.Value): Unit = w match {
  case Status.Ok => println("ok")
}
```

This compiles without a warning but will blow up at runtime:

```scala mdoc:crash
foo(Status.Nok)
```

[ADTs][ADT], on the other hand, do not suffer from this issue. Here's a better implementation of `Status`:

```scala mdoc:reset
sealed abstract class Status extends Product with Serializable
object Status {
  final case object Ok extends Status
  final case object Nok extends Status
}
```

The compiler now has enough information to check whether your pattern matches are exhaustive:

```scala mdoc:fail
def foo(w: Status): Unit = w match {
  case Status.Ok => println("ok")
}
```

[`Enumeration`]:https://www.scala-lang.org/api/2.12.8/scala/Enumeration.html
[ADT]:../definitions/adt.html


================================================
FILE: src/main/mdoc/_adts/errors_extend_exception.md
================================================
---
title: Make error ADTs subtypes of Exception
layout: article
---

> When creating an [ADT] to represent errors, have the base type extend [`Exception`].

# Reason

Some APIs, such as the standard [`Try`] and [`Future`], represent errors through exceptions. If your error type doesn't extend [`Exception`], you cannot stick it in a [`Failure`], for example.

Let's say we have this simple [ADT] for database-related errors:

```scala mdoc
sealed abstract class DbError extends Product with Serializable

object DbError {
  final case object InvalidSql extends DbError
  final case object ConnectionLost extends DbError
}
```

And for whatever reason, we need to implement the following method:

```scala
def foo(i: Int): Try[Int]
```

With our current `DbError` implementation, it's impossible to write something like:

```scala mdoc:fail
def foo(i: Int) = scala.util.Failure(DbError.InvalidSql)
```

Had `DbError` extended [`Exception`] however, this would have been perfectly possible:

```scala mdoc:reset
sealed abstract class DbError extends Exception with Product with Serializable

object DbError {
  final case object InvalidSql extends DbError
  final case object ConnectionLost extends DbError
}

def foo(i: Int) = scala.util.Failure(DbError.InvalidSql)
```

# Secondary reason

There's another reason for this rule, although I find it dubious.

Imagine you have two different error [ADTs][ADT] - our `DbError` one, and another that's more about business logic:

```scala mdoc
sealed abstract class UserError extends Exception with Product with Serializable

object UserError {
  final case object NotFound extends UserError
  final case object Unauthorized extends UserError
}
```

If you try to write a function that attempts to find a user in database and validate its password, its error type is either a `DbError` or a `UserError`. There are ways to represent that - [`Either`] (but that gets messy very quickly if we have more than 2 error types) or a unifying [ADT] that wraps both types, for instance.

Had both `DbError` and `UserError` extended [`Exception`], we'd have a third option: [`Exception`] being a sort of universal supertype for errors, we could just say that our error type is [`Exception`] and the compiler would be perfectly happy.

I personally dislike this approach. It removes the compiler's ability to check whether you've dealt with all error cases. You must manually choose which subtypes of [`Exception`] you want to deal with, and the compiler has no way of knowing if you've dealt with all error types for a given call, or if the types you deal with are actually possible in a given context.

[`Exception`]:https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Exception.html
[`Try`]:https://www.scala-lang.org/api/2.12.8/scala/util/Try.html
[`Future`]:https://www.scala-lang.org/api/2.12.8/scala/concurrent/Future.html
[`Failure`]:https://www.scala-lang.org/api/2.12.8/scala/util/Failure.html
[`Either`]:https://www.scala-lang.org/api/2.12.8/scala/util/Either.html
[ADT]:../definitions/adt.html


================================================
FILE: src/main/mdoc/_adts/final_case_objects.md
================================================
---
title: Mark case objects as final
layout: article
---

> When declaring a case object, make it [`final`].

# Reason

While case objects are effectively [`final`] in Scala - you can't extend them - they are not always flagged as such in the compiled bytecode.

Take the following code, for example:

```scala mdoc
class Test {
  case object foo
}
```

When `foo` is not flagged as [`final`], running the class file through `javap -c` yields the following (truncated) output:

```java
public class Test$foo$ implements scala.Product,scala.Serializable {
 // [...]
```

When it's flagged as [`final`], however, we get:

```java
public final class Test$foo$ implements scala.Product,scala.Serializable {
  // [...]
```

To make matters worse, this is not even coherent accross Scala versions - the previous output was obtained with 2.12.7, but 2.11.8, for example, will compile both versions of `Test.foo` as [`final`].

This might not seem like a big deal - as far as `scalac` is concerned, `Test.foo` is [`final`] either way and you won't be able to extend it - not having this information in the bytecode will:
* prevent the JIT from applying any [`final`]-specific optimisations
* potentially cause Java interop issues, since `javac` will let you extend `Test.foo`.

[`final`]:../definitions/final.html


================================================
FILE: src/main/mdoc/_adts/index.md
================================================
---
layout: section
---

[ADTs][adt] are a common and powerful way of representing data. Scala encodes them in a way that is (currently) a bit manual and heavy on the boilerplate, and there are a few rules to respect in order for the resulting types to be well behaved and idiomatic. This is what this section will be focusing on.

[adt]:../definitions/adt.html


================================================
FILE: src/main/mdoc/_adts/product_with_serializable.md
================================================
---
title: Make ADTs subtypes of Product and Serializable
layout: article
---

> When writing an [ADT], always have the root type extend [`Product`] and [`Serializable`].

# Reason

It allows the compiler to infer better types than it would otherwise.

Given the following simple [ADT]:

```scala mdoc
sealed abstract class Status
object Status {
  final case object Ok extends Status
  final case object Nok extends Status
}
```

The compiler will sometimes infer some wonky types:

```scala mdoc
List(Status.Ok, Status.Nok)
```

This happens because inferring types is done by looking at the most specific supertype of `Status.Ok` and `Status.Nok`.

`Status` *is* a supertype of both, but it's not the most specific one: `Status.Ok` and `Status.Nok` both also extend [`Product`] and [`Serializable`] by virtue of being case objects.

As far as the compiler is concerned, the most precise supertype it can find for both `Status.Ok` and `Status.Nok` is thus `Product with Serializable with Status`.

Now, consider the following implementation - the only difference is in the types that `Status` extend:

```scala mdoc:reset
sealed abstract class Status extends Product with Serializable
object Status {
  final case object Ok extends Status
  final case object Nok extends Status
}
```

Here, the most specific supertype of both `Status.Ok` and `Status.Nok` is `Status`, which leads to the correct types being inferred:

```scala mdoc
List(Status.Ok, Status.Nok)
```

[ADT]:../definitions/adt.html
[`Product`]:https://www.scala-lang.org/api/2.12.8/scala/Product.html
[`Serializable`]:https://www.scala-lang.org/api/2.12.8/scala/Serializable.html


================================================
FILE: src/main/mdoc/_binary_compat/abstract_over_trait.md
================================================
---
title: Prefer abstract classes to traits
layout: article
---

> When declaring an abstract type without a clear reason to prefer a `trait`, use an `abstract class`.

Since in most scenarios that aren't declaring an [ADT](../definitions/adt.html), it's impossible to guarantee that your type will never be involved in multiple inheritance, this rule can mostly be simplified to:

> When writing an [ADT](../definitions/adt.html), have the root type be an abstract class

# Reasons

## Binary compatibility

Adding a new concrete method to an existing trait breaks [binary compatibility](../definitions/binary_compatibility.html), which is a big deal for libraries.

The reason this happens has [been explained](https://stackoverflow.com/questions/18366817/is-adding-a-trait-method-with-implementation-breaking-backward-compatibility) far better than I could hope to do.

## Java interop

Traits can be a bit painful when you're writing Java code that has Scala dependencies. One concrete example of this is companion objects:

```scala mdoc
trait ATrait

object ATrait {
  def foo(): Int = 1
}

abstract class AnAbtractClass

object AnAbstractClass {
  def foo(): Int = 2
}
```

With these definitions, calling `foo` from Java code will look like:

```java
ATrait$.MODULE$.foo()

AnAbstractClass.foo()
```

Clearly, the abstract class version is more natural.

## It's a good default

The previous reasons don't really matter to projects that are not libraries or will never have to be used from Java code.

But abstract classes are not a worse choice than traits in most other scenarios (again, except when multiple inheritance is a possibility), and I prefer:

> When in doubt, use an abstract class.

to

> When in doubt and writing code that is or might become a library or is or might be called from Java, use an abstract class.


================================================
FILE: src/main/mdoc/_binary_compat/explicit_type_annotations.md
================================================
---
title: Add explicit type annotations to public members
layout: article
linters:
  - name: wartremover
    rules:
      - name: PublicInference
        url:  http://www.wartremover.org/doc/warts.html#publicinference
---

> Always add an explicit type to your public members, even when you're happy with what's being inferred.

# Reason

The compiler relies on implementation details to infer types, and implementation details can change - which can in turn break [binary compatibility][bincompat].

Type inference tries to work out the most specific subtype of all types a value could be. Take the following code, for example:

```scala mdoc
def foo(i: Int) = {
  if(i % 2 == 0) Some(i)
  else           None
}

foo(1)
```

[`Some[Int]`][`Some`] and [`None`] share a common direct supertype: [`Option[Int]`][`Option`] (well, [not quite](../adts/product_with_serializable.html), but close enough for our purposes). This allows the compiler to correctly infer `foo`'s return type, but what if we were to change the implementation in a later version?

```scala mdoc:reset
def foo(i: Int) = Some(i)

foo(1)
```

The return type is no longer [`Option[Int]`][`Option`] but [`Some[Int]`][`Some`], and just like that, we've broken [binary compatibility][bincompat].

Explicit type annotations on public members ensure that implementation details don't leak out and that we don't accidentally break things without meaning to, or even realizing.

# Mistaken assumption: implementing abstract members

A common assumption that turns out to be incorrect is that implementing abstract members (or overriding concrete ones) is fine, since the parent type will be inferred.

This turns out to be incorrect:

```scala mdoc
abstract class Foo {
  def getOpt[A](a: A): Option[A]
}

class FooImpl extends Foo {
  override def getOpt[A](a: A) = Some(a)
}
```

It's usually assumed that `FooImpl.getOpt` will return the right type, but this is wrong:

```scala mdoc
new FooImpl().getOpt(1)
```

Changing `FooImpl.getOpt` implementation to return either a [`Some[Int]`][`Some`] or an [`Option[Int]`][`Option`] will break [binary compatibility][bincompat] just as much as the general case.


[`Option`]:https://www.scala-lang.org/api/2.12.8/scala/Option.html
[`Some`]:https://www.scala-lang.org/api/2.12.8/scala/Some.html
[`Any`]:https://www.scala-lang.org/api/2.12.8/scala/Any.html
[bincompat]:../definitions/binary_compatibility.html
[`None`]:https://www.scala-lang.org/api/2.12.8/scala/None$.html


================================================
FILE: src/main/mdoc/_binary_compat/index.md
================================================
---
layout: section
---

[Binary compatibility][bincompat] is a matter of some importance to library authors - breaking it must only be done when there is no other choice, as it can have dire repercussions downstream.

We'll explore here a few perfectly innocent design decisions that can, and often will, eventually break [binary compatibility][bincompat] without the author realising it's happened.

[bincompat]:../definitions/binary_compatibility.html


================================================
FILE: src/main/mdoc/_definitions/adt.md
================================================
---
title: Algebraic Data Types
layout: definition
---

Algebraic Data Types (ADTs for short) are a way of structuring data. They're widely used in Scala due, mostly, to how well they work with pattern matching and how easy it is to use them to make illegal states impossible to represent.

There are two basic categories of ADTs:
* product types
* sum types

# Product types

A product type is essentially a way of sticking multiple values inside of one - a [`Tuple`], or something that's very similar to one. Case classes are the prototypical product type:

```scala mdoc
final case class Foo(b1: Boolean, b2: Boolean)
```

`Foo` aggregates two [`Boolean`] values.

It's called a _product_ type because we can compute its cardinality (the number of values it can possibly have) by calculating the product of the types that compose it.

Here, [`Boolean`] has an cardinality of 2 (it can only contain either `true` or `false`), and thus `Foo` must have an cardinality of 4. Indeed:
* `Foo(true, true)`
* `Foo(true, false)`
* `Foo(false, true)`
* `Foo(false, false)`

# Sum types

A sum type is a type that is composed of different possible values and value shapes. The simplest possible example is an enumeration - `Bool`, for example:

```scala mdoc
sealed abstract class Bool extends Product with Serializable

object Bool {
  final case object True extends Bool
  final case object False extends Bool
}
```

It's called a _sum_ type because its cardinality is equal to the sum of the arities of the types that compose it. Here, both `True` and `False` are singleton types, and `Bool` can indeed only have 2 possible values.

Sum types get a lot more interesting when you start using more complex data types for the alternatives.

# Bringing them together

Let's imagine a very simple language in which you can only give the following instructions:
* `move forward X meters`
* `rotate Y degrees`

A naïve implementation could be:

```scala mdoc
final case class Command(label: String, meters: Option[Int], degrees: Option[Int])
```

This is problematic, however, since it allows so many illegal states to be represented. For example:

```scala mdoc:silent
Command("foo", None, None)
Command("bar", Some(1), Some(2))
```

By reworking our type to a slightly more involved ADT, we get rid of these:

```scala mdoc:reset
sealed abstract class Command extends Product with Serializable

object Command {
  final case class Move(meters: Int) extends Command
  final case class Rotate(degrees: Int) extends Command
}
```

It's now impossible to create a value that makes no sense - either you move forward by X meters, or you rotate by Y degrees, nothing else.

This type also has the advantage of being very pattern match friendly:

```scala mdoc
def print(cmd: Command) = cmd match {
  case Command.Move(dist)    => println(s"Moving by ${dist}m")
  case Command.Rotate(angle) => println(s"Rotating by ${angle}°")
}
```

[`Tuple`]:https://www.scala-lang.org/api/2.12.8/scala/Tuple2.html
[`Boolean`]:https://www.scala-lang.org/api/2.12.8/scala/Boolean.html


================================================
FILE: src/main/mdoc/_definitions/binary_compatibility.md
================================================
---
title: Binary compatibility
layout: definition
---

Two versions of a library are said to be binary compatible if you can swap one for the other without recompiling.

Let's imagine a `Foo` library such that its `1.0.0` and `1.1.0` versions are binary incompatible (even though they are source compatible).
If you have three projects such that:
- `A` depends on `Foo 1.0.0`
- `B` depends on `Foo 1.1.0`
- `C` depends on `A` and `B`

Whoever maintains `C` will find himself dealing with some very weird runtime errors that might be a bit a nightmare to work out - that person might not even know that `Foo` exists, let alone that it's in `C`'s dependencies.

It's best to strive for binary compatibility for this reason. Tools such as [MiMa](https://github.com/lightbend/migration-manager) have been created to help library author with this task.


================================================
FILE: src/main/mdoc/_definitions/final.md
================================================
---
title: Final types
layout: definition
---

Marking a type as `final` means that it can never have subtypes.

For example, given:

```scala mdoc
final class Foo
```

Then the following can't compile:

```scala mdoc:fail
class Bar extends Foo
```


================================================
FILE: src/main/mdoc/_definitions/implicit_scope.md
================================================
---
title: Implicit scope
layout: definition
---

The implicit scope of a type `T` is where the compiler will look when attempting to locate implicit instances for that type. It is composed of all the companion objects of types associated with `T`.

To take a concrete example:

```scala mdoc
class Foo

object Foo {
  implicit val bar: List[Foo] = List.empty
}
```

`bar` is of type [`List[Foo]`][`List`], and is located within the companion object of `Foo`, a type associated with [`List[Foo]`][`List`]: it's in the implicit scope of [`List[Foo]`][`List`] and we need no special import for the compiler to locate it.

```scala mdoc
implicitly[List[Foo]]
```

The implicit scope is particularly helpful when defining [type class](type-class.html) instances.

[`List`]:https://www.scala-lang.org/api/2.12.8/scala/collection/immutable/List.html


================================================
FILE: src/main/mdoc/_definitions/paren-less.md
================================================
---
title: Paren-less methods
layout: definition
---

A paren-less method is a method that doesn't take parameters (a nullary method) and that is declared without parentheses:

```scala mdoc
def foo: Int = 1
```

Trying to call is with parentheses will fail:

```scala mdoc:fail
foo()
```

An interesting property of paren-less methods is that they can be overridden (or implemented, if abstract) by `val`s.


================================================
FILE: src/main/mdoc/_definitions/recursion.md
================================================
---
title: Recursion
layout: definition
---

A recursive function is one that calls itself. For example:

```scala mdoc
def sum(is: List[Int]): Int = is match {
  case h :: t => h + sum(t)
  case _      => 0
}
```

`sum` is implemented by referencing itself: the sum of a non empty list is the sum of its head plus the sum of its tail.


================================================
FILE: src/main/mdoc/_definitions/reference_equality.md
================================================
---
title: Reference equality
layout: definition
---

Reference equality is an equality relationship that does not only guarantee that two values are equal, but also that they are, in fact, the same value.

The distinction might not be obvious. It's possible to have two values that are equivalent - you can use one or the other to get the exact same result - but not the same. For example:

```scala mdoc:silent
val foo = Some(1)
val bar = foo
val baz = Some(1)
```

`foo`, `bar` and `baz` are all equal:

```scala mdoc
foo == bar

foo == baz

bar == baz
```

On the other hand, while `foo` and `bar` are the same value, `baz` isn't:

```scala mdoc
foo eq bar

foo eq baz

bar eq baz
```

Reference equality is rarely used, except when [warning people against it](../unsafe/array_comparison.html).


================================================
FILE: src/main/mdoc/_definitions/referential_transparency.md
================================================
---
title: Referential transparency
layout: definition
---

An expression is said to be referentially transparent if it can be replaced by its value and not change the program's behaviour.

For example, take the following method:

```scala mdoc
def add1(i: Int): Int = i + 1
```

It's referentially transparent because for any given `i`, you can use `add1(i)` or its result interchangeably.

This new version, however, isn't referentially transparent - we call such expressions _referentially opaque_:

```scala mdoc
def add1Bis(i: Int): Int = {
  println(i)
  i + 1
}
```

If it was referentially transparent, the two following methods would be strictly equivalent:

```scala mdoc
def foo1(i: Int): Int = {
  // We're using the result of add1Bis, twice.
  val a = add1Bis(i)

  a + a
}

def foo2(i: Int): Int =
  // We're calling add1Bis, twice.
  add1Bis(i) + add1Bis(i)
```

But they clearly are not:

```scala mdoc
foo1(1)

foo2(1)
```

# Why is it important?

This is more easily explained by showing what you lose without referentialy transparency.

```scala mdoc:silent
var i: Int = 1

def addi(j: Int): Int = i + j
```

`addi` is clearly not referentially transparent: it doesn't necessarily return the same value for the same input.

Now, let's start 10 threads that'll increment `i`:

```scala mdoc
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

for(_ <- (1 to 10)) scala.concurrent.Future(i += 1)
```

What do you think `addi(1)` evaluates to now? Well, there's no way to know. It could be any number between 1 and 12, depending on how many of our threads have already completed. Let's try:

```scala mdoc
addi(1)
```

This uncertainty is something we must strive to avoid at all costs - how do you write correct code if you're not sure what happens when you run it?

*This* is what referential transparency gets us: certainty, and understanding of how our code works.


# Related terms

You'll often hear talk of purity and side effects. Those are just other terms for referentially transparency or opacity:
* a function is pure if referentially transparent
* a side effect is what makes a function impure


================================================
FILE: src/main/mdoc/_definitions/sealed.md
================================================
---
title: Sealed types
layout: definition
---

Marking a type as `sealed` means that it can only have direct subtypes that are declared in the same source file.

For example, declaring this in, say, `Foo.scala`, will compile:

```scala mdoc
sealed class Foo

class Bar extends Foo
```

But the following, in `Baz.scala`, will not:

```scala mdoc
class Baz extends Foo
```

This is useful when all subtypes of a given type are known and we want to let the compiler know about it - typically, when working with [ADTs](adt.html).


================================================
FILE: src/main/mdoc/_definitions/tail_recursion.md
================================================
---
title: Tail recursion
layout: definition
---

A tail recursive function is a [recursive] function where the recursive call is the last thing to happen.

The following `sum` method is [recursive], but not tail recursive:

```scala mdoc
def sum(is: List[Int]): Int = is match {
  case h :: t => h + sum(t)
  case _      => 0
}
```

In the first `case`, `sum` calls itself *then* adds the result to the head of the list.

To make it tail recursive, we use an accumulator:

```scala mdoc:reset
def sum(is: List[Int]): Int = {
  def loop(cur: List[Int], acc: Int): Int = cur match {
    case h :: t => loop(t, acc + h)
    case _      => acc
  }
  loop(is, 0)
}
```

`sum` itself is not tail recursive - it's not even recursive anymore. On the other hand, `loop` is tail recursive: you can see that its last action is to call itself.

[recursive]:./recursion.html


================================================
FILE: src/main/mdoc/_definitions/total_function.md
================================================
---
title: Total functions
layout: definition
---

A function is said to be total if it's defined for it's entire domain. That is, `A => B` is total if there is a `B` for every possible `A`.

A function that is not total is said to be [partial](https://www.scala-lang.org/api/2.12.8/scala/PartialFunction.html).

For example, in the following code:

```scala mdoc
def int2str(i: Int): String = i.toString

def str2int(s: String): Int = Integer.parseInt(s)
```

* `int2str` is total because there exists no [`Int`] for which it's not defined.
* `str2int` is partial because there exists *many* [`Strings`][`String`] for which it isn't defined.

[`String`]:https://docs.oracle.com/javase/8/docs/api/java/lang/String.html
[`Int`]:https://www.scala-lang.org/api/2.12.8/scala/Int.html


================================================
FILE: src/main/mdoc/_definitions/type_class.md
================================================
---
title: Type class
layout: definition
---

In the context of Scala, a type class is a family of types that support a known set of behaviours. This could be, for example, the family of types that expose a unique integer identifier.

This is implemented through a `trait` and any number of implicit instances of that trait.

Here's how our _has a unique id_ type class could be represented:

```scala mdoc
trait HasId[A] {
  def getId(a: A): Int
}
```

If you manage to get your hands on an instance of `HasId[A]` for a given `A`, you know how to retrieve its id - however this is actually implemented in `A`.

Providing instances is done through implicits:

```scala mdoc:silent
final case class User(id: Int, name: String)

implicit val userHasId: HasId[User] = new HasId[User] {
  override def getId(user: User) = user.id
}
```

Instances are traditionally put in the companion object of either the type class or the type itself - here, either in `HasId` or `User`. Instances declared elsewhere (that  are not in the [implicit scope](./implicit_scope.html)) are said to be orphaned.

Instead of requiring a subtype of a known type, methods will require an implicit instance of the type class - a type and a proof that it supports the required behaviours.

For example:

```scala mdoc
def printId[A](a: A)(implicit hia: HasId[A]): Unit =
  println(s"Found id ${hia.getId(a)}")
```

`printId` isn't hard-coded to a single type, nor to a hierarchy of types with a known root, but to any type that can prove it supports the required behaviour - exposing an identifier.

This is a critical aspect of type classes: instances are linked to, but not baked into, types. You can provide instances later, or for types that you don't own.

Another important aspect is how type classes compose implicitly. Let's imagine the following:

```scala mdoc
trait HasLabel[A] {
  def getLabel(a: A): String
}
```

We could add immediate support for any type that has an `HasId` instance:

```scala mdoc
implicit def hasLabelFromId[A](implicit hia: HasId[A]): HasLabel[A] = new HasLabel[A] {
  override def getLabel(a: A) = s"ID:${hia.getId(a)}"
}
```

We can then rewrite our printing function:

```scala mdoc
def print[A](a: A)(implicit hla: HasLabel[A]): Unit =
  println(s"Label: ${hla.getLabel(a)}")
```

And to prove that this all works, let's call it on a `User`, for which we never explicitly provided an instance of `HasLabel`:

```scala mdoc
print(User(1, "Foo"))
```

We've essentially just told the compiler that any type that exposed an identifier was also capable of exposing a label.


================================================
FILE: src/main/mdoc/_oop/abstract_fields_as_defs.md
================================================
---
title: Declare abstract fields as paren-less methods
layout: article
---

> When declaring abstract fields in an abstract class or a trait, it's good practice to declare them as [paren-less] methods.

Prefer:

```scala mdoc
abstract class Foo {
  def bar: Int
}
```

Over:

```scala mdoc:reset
abstract class Foo {
  val bar: Int
}
```

# Reason

Scala allows abstract [paren-less] methods to be implemented as `val`s, but not the other way around.

Given the following:

```scala mdoc
abstract class AsDef {
  def bar: Int
}

abstract class AsVal {
  val bar: Int
}
```

Implementing `AsDef.bar` as a `val` compiles:

```scala mdoc:silent
new AsDef {
  override val bar = 0
}
```

But implementing `AsVal.bar` as a `def` does not:

```scala mdoc:fail
new AsVal {
  override def bar = 0
}
```

Declaring abstract fields as `val`s closes some possibilities, while declaring them as [paren-less] methods has no ill effect.

# Exceptions to the rule

There's at least one known scenario where declaring an abstract field as a `val` is important: path-dependent types, where its important that the field has a concrete type.

Here, for example:

```scala mdoc:silent:reset
trait Foo {
  val bar: String
}

val foo: Foo = new Foo {
  override val bar = "baz"
}
```

It's possible to to refer explicitly to the type of `foo.bar`:

```scala mdoc:silent
val fooBar: foo.bar.type = foo.bar
```

Had we defined `bar` as a `def`:

```scala mdoc:reset:silent
trait Foo {
  def bar: String
}

val foo: Foo = new Foo {
  override val bar = "baz"
}
```

Then we'd get a compilation error attempting to get the type of `foo.bar`:

```scala mdoc:fail
val fooBar: foo.bar.type = foo.bar
```


[paren-less]:../definitions/paren-less.html


================================================
FILE: src/main/mdoc/_oop/always_override.md
================================================
---
title: Use override when implementing abstract members
layout: article
linters:
  - name: wartremover
    rules:
      - name: MissingOverride
        url:  https://github.com/wartremover/wartremover-contrib#missingoverride
---

> When overriding a concrete member or implementing an abstract one, use the `override` keyword.

# Reason

This catches some scenarios where code would otherwise compile but misbehave at runtime.

Take the following trait, for example:

```scala mdoc
trait Foo[A] {
  // Default implementation
  def foo1(a: A): Int = 1
}
```

And now, an incorrect but valid implementation:

```scala mdoc:silent
implicit val badFooInt: Foo[Int] = new Foo[Int] {
  // Notice how this is not quite the right name.
  def fool(i: Int) = 2
}
```

This compiles, but is clearly not what the we intended: we wanted to implement `fool` but declared `foo1` instead. Since `fool` has a default implementation, this is valid but does not behave the way we think.

Had we used the `override` keyword, however, the compiler would have caught our error:

```scala mdoc:fail
implicit val fooInt: Foo[Int] = new Foo[Int] {
  override def fool(i: Int) = 2
}
```

# Alternatives

Another accepted practice is to *never* use `override` unless required by the language.

This comes from the fact that, for a certain subset of the Scala community, overriding (in the sense of redefining an existing method) is a code smell: the compiler can check that you're working with the right types, but not the invariants that are not expressed in the type system. A common example is implementing a `Set` as a subtype of a `Bag` (see [Subtyping, Subclassing, and Trouble with OOP](http://okmij.org/ftp/Computation/Subtyping/) for an in-depth discussion).

Given that premise, the argument is that since overriding is bad, you should treat the use of the `override` keyword like you would an instruction to silence compiler warnings: explicit acknowledgement that you're doing something unsavoury.

This debate would be solved by adding a new `implement` keywords, similar to `override` but only used to flag members that you expect to implement abstract members in a superclass. This doesn't exist however, and I feel the pragmatic approach is to follow the rule that catches bad programs rather than the purely ideological one.


================================================
FILE: src/main/mdoc/_oop/index.md
================================================
---
layout: section
---

While it should be fairly obvious by now that I lean more on the FP part of the Scala community, the language *does* have a large set of OOP features.

When these are the right tools for the job at hand, developers should feel absolutely free to use them. But with care, and if possible while keeping in mind the rules exposed in this section.


================================================
FILE: src/main/mdoc/_partial_functions/either_projection_get.md
================================================
---
title: Do not call get on an Either projection
layout: article
linters:
  - name: wartremover
    rules:
      - name: EitherProjectionPartial
        url:  http://www.wartremover.org/doc/warts.html#eitherprojectionpartial
  - name: scapegoat
    rules:
      - name: EitherGet
---

> When retrieving the content of an [`Either`], do not use [`get`] on one of its projections.

# Reason

Some projections are [left projections][`LeftProjection`] of a [`Right`], or [right projections][`RightProjection`] of a [`Left`], and [`get`] deals with them by throwing an exception:

```scala mdoc:crash
Left(1).right.get
```

```scala mdoc:crash
Right(1).left.get
```

If you have a default value to provide for the "other" case, use [`getOrElse`] on a projection:

```scala mdoc
Left(1).right.getOrElse(-1)
```

Alternatively, if you're using the common convention of treating the [`Left`] side of an [`Either`] as the error case, you can also call [`getOrElse`][biasedGetOrElse] directly on the [`Either`]:

```scala mdoc
Left(1).getOrElse(-1)
```

Another practical approach is to use [`fold`], which lets you provide a handler for each case:

```scala mdoc
(Left(1): Either[Int, Boolean]).fold(
  i => s"Found an int: '$i'",
  b => s"Found a boolean: '$b'"
)
```

[`Either`]:https://www.scala-lang.org/api/2.12.8/scala/util/Either.html
[`Right`]:https://www.scala-lang.org/api/2.12.8/scala/util/Right.html
[`Left`]:https://www.scala-lang.org/api/2.12.8/scala/util/Left.html
[`RightProjection`]:https://www.scala-lang.org/api/2.12.8/scala/util/Either$$RightProjection.html
[`LeftProjection`]:https://www.scala-lang.org/api/2.12.8/scala/util/Either$$LeftProjection.html
[`fold`]:https://www.scala-lang.org/api/2.12.8/scala/util/Either.html#fold[C](fa:A=%3EC,fb:B=%3EC):C
[`getOrElse`]:https://www.scala-lang.org/api/2.12.8/scala/util/Either$$RightProjection.html#getOrElse[B1%3E:B](or:=%3EB1):B1
[`get`]:https://www.scala-lang.org/api/2.12.8/scala/util/Try.html#get:T
[biasedGetOrElse]:https://www.scala-lang.org/api/2.12.8/scala/util/Either.html#getOrElse[B1%3E:B](or:=%3EB1):B1


================================================
FILE: src/main/mdoc/_partial_functions/index.md
================================================
---
layout: section
---

Scala, like a lot of other languages, sometimes takes shortcuts in its standard library to meet common expectations. We'll be focusing here on all the [partial functions](../definitions/total_function.html) that are commonly abused and really shouldn't have been there in the first place, and how to avoid them.


================================================
FILE: src/main/mdoc/_partial_functions/option_get.md
================================================
---
title: Do not call get on an Option
layout: article
linters:
  - name: wartremover
    rules:
      - name: OptionPartial
        url:  http://www.wartremover.org/doc/warts.html#optionpartial
  - name: scapegoat
    rules:
      - name: OptionGet
---

> When retrieving the content of an [`Option`], do not use [`get`].

# Reason

Some [`Options`][`Option`] are [`Nones`][`None`], and [`get`] deals with them by throwing an exception:

```scala mdoc:crash
None.get
```

If you have a default value to provide for the [`None`] case, use [`getOrElse`]:

```scala mdoc
None.getOrElse(-1)
```

Another practical approach is to use [`fold`], which lets you provide a handler for each case:

```scala mdoc
(None: Option[String]).fold("Found None")(i => s"Found an int: '$i'")
```

[`Option`]:https://www.scala-lang.org/api/2.12.8/scala/Option.html
[`None`]:https://www.scala-lang.org/api/2.12.8/scala/None$.html
[`get`]:https://www.scala-lang.org/api/2.12.8/scala/Option.html#get:A
[`getOrElse`]:https://www.scala-lang.org/api/2.12.8/scala/Option.html#getOrElse[B%3E:A](default:=%3EB):B
[`fold`]:https://www.scala-lang.org/api/2.12.8/scala/Option.html#fold[A1%3E:A](z:A1)(op:(A1,A1)=%3EA1):A1


================================================
FILE: src/main/mdoc/_partial_functions/traversable_head.md
================================================
---
title: Avoid using head
layout: article
linters:
  - name: wartremover
    rules:
      - name: TraversableOps
        url:  http://www.wartremover.org/doc/warts.html#traversableops
  - name: scapegoat
    rules:
      - name: TraversableHead
---

> When retrieving the head of a sequence, use [`headOption`] rather than [`head`].

# Reason

Some collections are empty, and [`head`] deals with them by throwing an exception:

```scala mdoc:crash
Seq.empty[Int].head
```

[`headOption`] is a safer alternative, since it encodes the possibility of the empty list in its return type:

```scala mdoc
Seq(1, 2, 3).headOption

Seq.empty[Int].headOption
```

[`head`]:https://www.scala-lang.org/api/2.12.8/scala/collection/Seq.html#head:A
[`headOption`]:https://www.scala-lang.org/api/2.12.8/scala/collection/Seq.html#headOption:Option[A]


================================================
FILE: src/main/mdoc/_partial_functions/traversable_init.md
================================================
---
title: Avoid using init
layout: article
linters:
  - name: wartremover
    rules:
      - name: TraversableOps
        url:  http://www.wartremover.org/doc/warts.html#traversableops
---

> When retrieving everything but the last element of a sequence, do not use [`init`]. [`dropRight(1)`] is often what you want to use.

# Reason

Some collections are empty, and [`init`] deals with them by throwing an exception:

```scala mdoc:crash
Seq.empty[Int].init
```

[`dropRight(1)`], on the other hand, will yield a reasonable value: the empty list.

```scala mdoc
Seq(1, 2, 3).dropRight(1)

Seq.empty[Int].dropRight(1)
```

# Exceptions to the rule

Note that this is not *always* what you want to do. There are scenarios in which you must deal with the empty case explicitly - as a stop condition in a recursive function, say.
It's just that, often, getting the empty list when you ask for everything but the last element of an empty list is perfectly reasonable.

[`dropRight(1)`]:https://www.scala-lang.org/api/2.12.8/scala/collection/Seq.html#dropRight(n:Int):Repr
[`init`]:https://www.scala-lang.org/api/2.12.8/scala/collection/Seq.html#init:Repr


================================================
FILE: src/main/mdoc/_partial_functions/traversable_last.md
================================================
---
title: Avoid using last
layout: article
linters:
  - name: wartremover
    rules:
      - name: TraversableOps
        url:  http://www.wartremover.org/doc/warts.html#traversableops
  - name: scapegoat
    rules:
      - name: TraversableLast
---

> When retrieving the last element of a sequence, use [`lastOption`] rather than [`last`].

# Reason

Some collections are empty, and [`last`] deals with them by throwing an exception:

```scala mdoc:crash
Seq.empty[Int].last
```

[`lastOption`] is a safer alternative, since it encodes the possibility of the empty list in its return type:

```scala mdoc
Seq(1, 2, 3).lastOption

Seq.empty[Int].lastOption
```

[`last`]:https://www.scala-lang.org/api/2.12.8/scala/collection/Seq.html#last:A
[`lastOption`]:https://www.scala-lang.org/api/2.12.8/scala/collection/Seq.html#lastOption:Option[A]


================================================
FILE: src/main/mdoc/_partial_functions/traversable_reduce.md
================================================
---
title: Avoid using reduce
layout: article
linters:
  - name: wartremover
    rules:
      - name: TraversableOps
        url:  http://www.wartremover.org/doc/warts.html#traversableops
---

> When reducing a collection to a single value, prefer [`reduceOption`] to [`reduce`].

# Reason

Some collections are empty, and [`reduce`] deals with them by throwing an exception:

```scala mdoc:crash
Seq.empty[Int].reduce(_ + _)
```

[`reduceOption`] is a safer alternative, since it encodes the possibility of the empty list in its return type:

```scala mdoc
Seq(1, 2, 3).reduceOption(_ + _)

Seq.empty[Int].reduceOption(_ + _)
```

[`reduce`]:https://www.scala-lang.org/api/2.12.8/scala/collection/Seq.html#reduce[A1%3E:A](op:(A1,A1)=%3EA1):A1
[`reduceOption`]:https://www.scala-lang.org/api/2.12.8/scala/collection/Seq.html#reduceOption[A1%3E:A](op:(A1,A1)=%3EA1):Option[A1]


================================================
FILE: src/main/mdoc/_partial_functions/traversable_tail.md
================================================
---
title: Avoid using tail
layout: article
linters:
  - name: wartremover
    rules:
      - name: TraversableOps
        url:  http://www.wartremover.org/doc/warts.html#traversableops
---

> When retrieving everything but the first element of a sequence, do not use [`tail`]. [`drop(1)`] is often what you want to use.

# Reason

Some collections are empty, and [`tail`] deals with them by throwing an exception:

```scala mdoc:crash
Seq.empty[Int].tail
```

[`drop(1)`], on the other hand, will yield a reasonable value: the empty list.

```scala mdoc
Seq(1, 2, 3).drop(1)

Seq.empty[Int].drop(1)
```

# Exceptions to the rule

Note that this is not *always* what you want to do. There are scenarios in which you must deal with the empty case explicitly - as a stop condition in a recursive function, say.
It's just that, often, getting the empty list when you ask for everything but the first element of an empty list is perfectly reasonable.

[`tail`]:https://www.scala-lang.org/api/2.12.8/scala/collection/Seq.html#tail:A
[`drop(1)`]:https://www.scala-lang.org/api/2.12.8/scala/collection/Seq.html#drop(n:Int):Repr


================================================
FILE: src/main/mdoc/_partial_functions/try_get.md
================================================
---
title: Do not call get on an Try
layout: article
linters:
  - name: wartremover
    rules:
      - name: TryPartial
        url:  http://www.wartremover.org/doc/warts.html#trypartial
  - name: scapegoat
    rules:
      - name: TryGet
---

> When retrieving the content of a [`Try`], do not use [`get`].

# Reason

Some [`Trys`][`Try`] are [`Failures`][`Failure`], and [`get`] deals with them by throwing an exception.

```scala mdoc:crash
scala.util.Failure(new Exception).get
```

If you have a default value to provide in case of a [`Failure`], use [`getOrElse`]:

```scala mdoc
scala.util.Failure(new Exception).getOrElse(-1)
```

Another practical approach is to use [`fold`], which lets you provide a handler for each case:

```scala mdoc
import scala.util.{Failure, Try}

(Failure(new Exception): Try[Int]).fold(
  e => s"Found an error: '${e.getMessage}'",
  i => s"Found an int: '$i'"
)
```

[`Try`]:https://www.scala-lang.org/api/2.12.8/scala/util/Try.html
[`getOrElse`]:https://www.scala-lang.org/api/2.12.8/scala/util/Try.html#getOrElse[U%3E:T](default:=%3EU):U
[`fold`]:https://www.scala-lang.org/api/2.12.8/scala/util/Try.html#fold[U](fa:Throwable=%3EU,fb:T=%3EU):U
[`get`]:https://www.scala-lang.org/api/2.12.8/scala/util/Try.html#get:T
[`Failure`]:https://www.scala-lang.org/api/2.12.8/scala/util/Failure.html
[`Success`]:https://www.scala-lang.org/api/2.12.8/scala/util/Success.html


================================================
FILE: src/main/mdoc/_referential_transparency/avoid_mutability.md
================================================
---
title: Avoid mutability
layout: article
linters:
  - name: wartremover
    rules:
      - name: Var
        url:  http://www.wartremover.org/doc/warts.html#var
      - name: MutableDataStructures
        url: http://www.wartremover.org/doc/warts.html#mutabledatastructures
---

> Mutability is almost always a bad idea and should be avoided.

# Reasons

## It's referentially opaque

Mutability very often breaks [referential transparency][reftrans].

Let's take the following method:

```scala mdoc:silent
var i: Int = 0

def foo(j: Int): Int = {
  i += j
  i
}
```

If it were [referentially transparent][reftrans], it'd always yield the same output for the same input. This is clearly not true:

```scala mdoc
foo(1)

foo(1)
```


## It's often premature optimisation

Mutability is very often (but not always) used for performance reasons - it's unfortunately been drilled into generations of programmers that instance reuse is the key to fast code.

There are a few problems with that assertion, though. First, it's just not really true - immutable data structures, for example, often have the same asymptotic complexity as their mutable counterparts, and are much, much simpler to both implement and work with.

Whether or not you believe this to be true, however, is irrelevant, provided you agree that you use mutability to write faster code. If you agree with that, then you agree that mutability is an optimisation - it means the same thing. And optimisations, especially ones that come at such a high cost ([referential opacity][reftrans]), should only be applied when they actually matter, not by default. Optimising by default is called _premature optimisation_ and it's not a good thing.

Whenever you feel like using mutability, ask yourself if it's actually worth it. Run benchmarks! If mutability gets you an incredible 50% speedup on a bit of code that's 1% of your runtime, that's a 0.5% speedup overall. Is that really worth the maintenance / complexity cost?

# Exceptions to the rule

Mutability is acceptable when it doesn't break [referential transparency][reftrans]. The most typical example of that is local mutability:

```scala mdoc
def sum(is: List[Int]): Int = {
  var s = 0
  for(i <- is) s += i
  s
}
```

The fact that `s` is mutable isn't exposed to the rest of the world and `sum` is [referentially transparent][reftrans]. If using mutability this way solves some performance bottleneck, go for it!

Just for the record though, this example is much cleaner without mutability:

```scala mdoc:reset
def sum(is: List[Int]): Int = is.fold(0)(_ + _)
```


[reftrans]:../definitions/referential_transparency.html


================================================
FILE: src/main/mdoc/_referential_transparency/avoid_return.md
================================================
---
title: Do not use return
layout: article
linters:
  - name: wartremover
    rules:
      - name: Return
        url:  http://www.wartremover.org/doc/warts.html#return
  - name: scapegoat
    rules:
      - name: UnnecessaryReturnUse
  - name: scalastyle
    rules:
      - name: ReturnChecker
        url:  http://www.scalastyle.org/rules-1.0.0.html#org_scalastyle_scalariform_ReturnChecker
---

> There's never a good reason to use the `return` keyword.

# Reasons

## It makes code hard to reason about

There's an argument to be made that the more ways there are to reach a given line of code, the harder that code is to reason about.

See [GOTO statements considered harmful] for an eloquent dissertation on the matter.

## It's referentially opaque

If `return` were [referentially transparent][reftrans], you should be able to inline expressions that use it and not change the meaning of a program.

Here's `foo1`, a method whose return values are pre-computed and stored in values:

```scala mdoc
def foo1(i: Int): Int = {
  val pos = return i
  val neg = return -i

  if(i > 0) pos
  else      neg
}
```

And `foo2`, the same method but with the return values inlined:

```scala mdoc
def foo2(i: Int): Int = {
  if(i > 0) return i
  else      return -i
}
```

If `return` was [referentially transparent][reftrans], we'd get the same `foo1` and `foo2` output for the same input, but:

```scala mdoc
foo1(-1)
foo2(-1)
```

## You (probably) don't understand what it does

Let's take the following, fairly straightforward method:

```scala mdoc:fail
def foo(is: List[Int]): List[Int] = is.map(n => return n + 1)
```

The compilation error doesn't seem to make much sense - how can a [`map`] on a [`List[Int]`][`List`] yield an [`Int`]? But the compiler tends to be smarter than us about these things, so let's play along.

```scala mdoc:fail
def foo(is: List[Int]): Int = is.map(n => return n + 1)
```

It's unclear how [`Nothing`] got mixed up in there, and is usually the sign that something went south, but fine, down the rabbit hole we go:


```scala mdoc:fail
def foo(is: List[Int]): List[Nothing] = is.map(n => return n + 1)
```

`(╯°□°)╯︵ ┻━┻`

I don't understand what's going on there, nor do I really want to. `return` is mad. Don't use it.

[`List`]:https://www.scala-lang.org/api/2.12.8/scala/collection/immutable/List.html
[`map`]:https://www.scala-lang.org/api/2.12.8/scala/collection/immutable/List.html#max:A
[GOTO statements considered harmful]:https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf
[`Nothing`]:https://www.scala-lang.org/api/2.12.8/scala/Nothing.html
[`Int`]:https://www.scala-lang.org/api/2.12.8/scala/Int.html
[reftrans]:../definitions/referential_transparency.html


================================================
FILE: src/main/mdoc/_referential_transparency/avoid_throwing_exceptions.md
================================================
---
title: Do not throw exceptions
layout: article
linters:
  - name: wartremover
    rules:
      - name: Throw
        url:  http://www.wartremover.org/doc/warts.html#throw
---

> Do not throw exceptions if you can possibly avoid it.

In particular, when:
* something might not be there, use [`Option`].
* something might fail, use [`Either`].
* something is rude and might throw an [`Exception`], use [`Try`].

# Reasons

## They're referentially opaque

Throwing an [`Exception`] breaks [referential transparency][reftrans].

This can be demonstrated fairly easily. If `throw` was [referentially transparent][reftrans], by definition, the two following methods would be equivalent:

```scala mdoc
def foo1() = if(false) throw new Exception else 2

def foo2() = {
  val a = throw new Exception
  if (false) a  else 2
}
```

Turns out, however, that they aren't.

`foo1` terminates:

```scala mdoc
foo1()
```

`foo2` fails with an exception:

```scala mdoc:crash
foo2()
```

## They're unsafe

Scala uses unchecked exceptions, which means that the compiler is not aware of them, and cannot check whether they're dealt with properly. A function that throws is a bit of a lie: its type implies it's [total function](../definitions/total_function.html) when it's not.

Let's take a trivial example:

```scala mdoc
def foo(i: Int) = throw new Exception
```

As far as the type checker is concerned, this function is perfectly fine and it'll happily accept the following:

```scala mdoc:crash
foo(1)
```

This blows up at runtime, which is really something we'd like to avoid.

# Exceptions to the rule

It's perfectly fine to throw an exception for truly exceptional errors. CPU not found? Critical hard-drive failure? a required resource hasn't been bundled with the binaries? throw away.

But scenarios such as _parse this string into an int_ should never throw - a [`String`] not being an [`Int`] is not exceptional, it's the normal case! There are many more [`String`]s that aren't valid [`Int`]s than the converse.

[`Exception`]:https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html
[reftrans]:../definitions/referential_transparency.html
[`Int`]:https://www.scala-lang.org/api/2.12.8/scala/Int.html
[`String`]:https://docs.oracle.com/javase/8/docs/api/java/lang/String.html
[`Option`]:https://www.scala-lang.org/api/2.12.8/scala/Option.html
[`Try`]:https://www.scala-lang.org/api/2.12.8/scala/util/Try.html
[`Either`]:https://www.scala-lang.org/api/2.12.8/scala/util/Either.html


================================================
FILE: src/main/mdoc/_referential_transparency/index.md
================================================
---
layout: section
---

[Referential transparency][reftrans] is a big deal in FP - it's basically the core of what functional programming is.

Scala, being the hybrid that it is, has features that are commonly used in imperative languages but break [referential transparency][reftrans] by their very existence. We'll explore the most common (and dangerous) ones here.

And for readers that are in the "Scala as an imperative language" part of the community: even then, [referential transparency][reftrans] is a useful property, a good default to strive for but break when needed.

[reftrans]:../definitions/referential_transparency.html


================================================
FILE: src/main/mdoc/_tricky_behaviours/final_case_classes.md
================================================
---
title: Mark case classes as final
layout: article
linters:
  - name: wartremover
    rules:
      - name: FinalCaseClass
        url:  http://www.wartremover.org/doc/warts.html#finalcaseclass
  - name: scapegoat
    rules:
      - name: FinalModifierOnCaseClass
---

> When declaring a case class, make it [`final`].

# Reason

Extending a case class will produce behaviours that, while perfectly correct, can be surprising and certainly break reasonable expectations.

For example:

```scala mdoc
case class Foo(i: Int)
class Bar(i: Int, s: String) extends Foo(i)
```

`Bar` will behave oddly when it comes to comparison, hashing and printing:

```scala mdoc
new Bar(1, "foo") == new Bar(1, "bar")

Map(
  new Bar(1, "foo") -> "foo",
  new Bar(1, "bar") -> "bar"
)

new Bar(1, "baz")
```

This is largely due to Scala's reliance on Java constructs. In this instance:
* [`equals`], used to compare two values (and which maps to `==` in Scala)
* [`hashCode`], used to compute the hash of a value
* [`toString`], used to represent a value as a [`String`]

Case classes will generate correct implementations of these methods - [`equals`], for example, will run a field-for-field comparison.
The problem is that this breaks when you extend a case class: the subclass will inherit these methods, which are not aware of any field you might have added.

In the case of our `Bar` example, the `s` field is ignored by [`equals`], [`toString`] and [`hashCode`], which leads to the surprising (but perfectly correct) behaviour we observed.

# Exceptions to the rule

There's at least one scenario I know of where a non-[`final`] case class is desirable: when you wish to declare a case class but have absolute control over the values of its fields.

Let's say, for example, that you want to create a `PositiveInt` type wrapping an [`Int`] that is guaranteed to be positive. A naïve implementation would be:

```scala mdoc
final case class PositiveInt(value: Int)

object PositiveInt {
  def fromInt(i: Int): Option[PositiveInt] =
    if(i > 0) Some(new PositiveInt(i))
    else      None
}
```

The problem with this implementation is that you still have many ways to create values of type `PositiveInt` that containing a negative [`Int`]:

```scala mdoc
new PositiveInt(-1)

PositiveInt.fromInt(1).map(_.copy(-1))
```

In order to seal these holes, a common trick is to declare a `sealed abstract case class`:

```scala mdoc:reset
sealed abstract case class PositiveInt(value: Int)

object PositiveInt {
  def fromInt(i: Int): Option[PositiveInt] =
    if(i > 0) Some(new PositiveInt(i) {})
    else      None
}
```

Since `PositiveInt` is abstract, the compiler can't generate a constructor, a `copy` method or an `apply` method on the companion object and you effectively control the values that get inside it. But this requires it not to be [`final`].

So, as is often the case, there are scenarios in which this rule must be broken. It's a good default behaviour, to be changed when you must.

[`equals`]:https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-
[`hashCode`]:https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--
[`toString`]:https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#toString--
[`Int`]:https://www.scala-lang.org/api/2.12.8/scala/Int.html
[`final`]:../definitions/final.html
[`String`]:https://docs.oracle.com/javase/8/docs/api/java/lang/String.html


================================================
FILE: src/main/mdoc/_tricky_behaviours/future_in_comprehensions.md
================================================
---
title: Start independent Futures outside of a for-comprehension
layout: article
---

> When working with independent [`Futures`][`Future`], make sure not to initialise them inside a for-comprehension.

# Reason

For-comprehension will create a dependency between your [`Futures`][`Future`], turning your code synchronous behind your back.

To understand how this can happen, it's important to realise that for-comprehensions are just syntactic sugar for nested [`flatMap`] and [`map`] calls.

Take the following code:

```scala mdoc:reset-class
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global

def longRunning(): Int = {
  Thread.sleep(100)
  println("LONG")
  1
}

def immediate(): Int = {
  println("IMMEDIATE")
  2
}

def combine(): Future[Int] = for {
  i <- Future(longRunning())
  j <- Future(immediate())
} yield i + j
```

`combine` desugars to:

```scala mdoc
def desugaredCombine(): Future[Int] =
  Future(longRunning()).flatMap { i =>
    Future(immediate()).map(j => i + j)
  }
```

This means that the second [`Future`] (the one that yields `2`) cannot be started before the first one has completed - `i` is in its scope, even if not used - even though these two [`Futures`][`Future`] are clearly independent from each other.

To make this evident, let's evaluate `combine`. However many times you run it, `LONG` will always be printed before `IMMEDIATE`, even though the former is executed after a significant delay:

```scala mdoc
Await.result(combine(), 500.millis)
```

This can be worked around by creating the two [`Future`] instances outside of the for-comprehension: [`Future`] has the controversial behaviour that it starts executing when created, not when evaluated.

```scala mdoc
def betterCombine(): Future[Int] = {
  val f1 = Future(longRunning())
  val f2 = Future(immediate())

  for {
    i <- f1
    j <- f2
  } yield i + j
}
```

And if we now evaluate `betterCombine`, the log messages should print in the expected order:

```scala mdoc
Await.result(betterCombine(), 200.millis)
```

[`Future`]:https://www.scala-lang.org/api/2.12.8/scala/concurrent/Future.html
[`flatMap`]:https://www.scala-lang.org/api/2.12.8/scala/concurrent/Future.html#flatMap[S](f:T=%3Escala.concurrent.Future[S])(implicitexecutor:scala.concurrent.ExecutionContext):scala.concurrent.Future[S]
[`map`]:https://www.scala-lang.org/api/2.12.8/scala/concurrent/Future.html#map[S](f:T=%3ES)(implicitexecutor:scala.concurrent.ExecutionContext):scala.concurrent.Future[S]


================================================
FILE: src/main/mdoc/_tricky_behaviours/implicit_shadowing.md
================================================
---
title: Make implicit names as unique as possible
layout: article
---

> When declaring an implicit value or method, try to give it a name that minimises the chances of conflicting with other libraries.

# Reason

Implicit names shadow each other and confuse the compiler (and developers).

For example:

```scala mdoc
object foo {
  implicit val bar: Int = 1
}

object baz {
  implicit val bar: String = "foo"
}
```

Note how both `foo` and `baz` contain a value called `bar`, even though they do not share a type and only one is implicit.

This yields the following, confusing behaviour:

```scala mdoc:fail
import foo._, baz._

implicitly[Int]
```

There's a single implicit value of type [`Int`] in scope - `foo.bar`. But the compiler can't find it.

One way of demonstrating *why* the compiler cannot find it is:

```scala mdoc:fail
import foo._, baz._

val a: String = bar
```

Even in the presence of sufficient type information (we know that `a` is a [`String`], and only one of the two `bar`s in scope is a [`String`]), the compiler considers two clashing names to be ambiguous and demands the ambiguity fixed.

The problem is easy to understand and fix in this last example - the error message is quite explicit. But in the context of implicit resolution, we're just getting a generic _could not find implicit value_ error message, which can be a bit of a nigthmare to debug.

In order to avoid this, and since you cannot control how other libraries name their implicits, you must:
* give yours very, very unique names - it doesn't matter if they look silly, they're implicits, the idea is to not refer to them by name
* hope that other libraries do the same

# Exceptions to the rule

There's at least one scenario in which an implicit's name isn't used during resolution: when you declare an implicit of type `T` in the [implicit scope](../definitions/implicit_scope.html) of `T`.

For example:

```scala mdoc:reset:silent
trait Foo[A]
object Foo {
  implicit val foo: Foo[Int] = new Foo[Int] {}
}

trait Bar[A]
object Bar {
  implicit val foo: Bar[String] = new Bar[String] {}
}
```

Even though both implicit values share the name `foo`, implicit resolution works out:

```scala mdoc
// Brings Foo.foo and Bar.foo in scope
import Foo._, Bar._

// No conflict here
implicitly[Foo[Int]]
```

In this scenario, it's safe to give terse names to your implicits.

[`Int`]:https://www.scala-lang.org/api/2.12.8/scala/Int.html
[`String`]:https://docs.oracle.com/javase/8/docs/api/java/lang/String.html


================================================
FILE: src/main/mdoc/_tricky_behaviours/index.md
================================================
---
layout: section
---

This section explores aspects of Scala that break reasonable expectations or cause cryptic compilation errors. They're easily avoided if you know about them, but have been known to mystify beginners and more advanced developers alike.


================================================
FILE: src/main/mdoc/_tricky_behaviours/leaky_sealed_types.md
================================================
---
title: Make subtypes of sealed types final
layout: article
linters:
  - name: wartremover
    rules:
      - name: LeakingSealed
        url:  http://www.wartremover.org/doc/warts.html#leakingsealed
---

> When writing a subtype for a [`sealed`] type, mark it as [`final`].

# Reason

Most people will instinctively assume that a [`sealed`] type cannot have implementations in another source file - that's what a type being [`sealed`] means, right?

Well, not quite. A [`sealed`] type can only have *direct* subtypes in the same source file. But the constraint is not transitive and these subtypes, not being [`sealed`] themselves, can have subtypes declared in other files.

For example, having this in one file:

```scala mdoc
sealed trait Foo

class Bar extends Foo
```

We can absolutely extend `Bar` in another source file:

```scala mdoc
class FooBar extends Bar
```

This is perfectly correct as per the definition of [`sealed`], and sometimes even desirable. It's just not what most people expect.

For this reason, it's preferable to default to [`final`] subtypes unless you have a good reason for them not to be.

[`sealed`]:../definitions/sealed.html
[`final`]:../definitions/final.html


================================================
FILE: src/main/mdoc/_tricky_behaviours/string_concatenation.md
================================================
---
title: Do not concatenate Strings with +
layout: article
linters:
  - name: wartremover
    rules:
      - name: StringPlusAny
        url:  http://www.wartremover.org/doc/warts.html#stringplusany
---

> When concatenating something to a [`String`], consider string interpolation rather than [`+`].

# Reason

Because of a little gem called [`any2stringadd`], [`+`] is just not very sane in Scala.

It has, for example, wildly different behaviours for similar collections:

```scala mdoc
List("foo") + "bar"

Set("foo") + "bar"
```

[`+`] also causes this kind of absolutely nonsensical error message:

```scala mdoc:fail
List(1) + 2
```

This is because of my old nemesis, [implicit conversions](../unsafe/implicit_conversions.html). What the compiler actually ends up trying is:

```scala mdoc:fail:silent
any2stringadd(List(1)).+(2)
```

It makes sense when you understand the underlying mechanisms, but good luck explaining that to a beginner.

String interpolation, on the other hand, is safe and coherent:

```scala mdoc
s"${List("foo")}bar"

s"${Set("foo")}bar"

s"${List(1)}${2}"
```

[`+`]:https://www.scala-lang.org/api/2.12.8/scala/Any.html#+(other:String):String
[`String`]:https://docs.oracle.com/javase/8/docs/api/java/lang/String.html
[`any2stringadd`]:https://www.scala-lang.org/api/2.12.8/scala/Predef$.html#any2stringadd[A]extendsAnyVal


================================================
FILE: src/main/mdoc/_tricky_behaviours/type_implicits.md
================================================
---
title: Add explicit type annotations to implicits
layout: article
linters:
  - name: wartremover
    rules:
      - name: ExplicitImplicitTypes
        url:  http://www.wartremover.org/doc/warts.html#explicitimplicittypes
---

> Always add an explicit type to your implicit values or methods, even when they're private

# Reason

Aside from [binary compatibility concerns](../binary_compat/explicit_type_annotations.html), implicit resolution is complex and, sometimes, buggy.

The following code compiles:

```scala mdoc:silent
trait Foo[_]
class Bar

implicitly[Foo[Bar]]

object Bar {
  implicit val impFoo: Foo[Bar] = new Foo[Bar] {}
}
```

`impFoo` is in the [implicit scope](../definitions/implicit_scope.html) of `Foo[Bar]`, and our `implicitly[Foo[Bar]]` resolves.

But, because of [bug 8697](https://github.com/scala/bug/issues/8697), the following does not:

```scala mdoc:reset:fail
trait Foo[_]
class Bar

implicitly[Foo[Bar]]

object Bar {
  implicit val impFoo = new Foo[Bar] {}
}
```

The only difference between the two is that `impFoo` has an explicit type in the first snippet but not in the second.

The behaviour is clearly counter-intuitive, and considered to be a bug - but it results in a compilation failure that's trivial to fix once you know the problem.

Well. Most of the time. There are [cases](https://github.com/rickynils/scalacheck/pull/468) where it will result in the *wrong* implicit value being picked, which is a lot harder to realise and fix.


================================================
FILE: src/main/mdoc/_tricky_behaviours/unicode_operators.md
================================================
---
title: Avoid unicode versions of ASCII operators
layout: article
linters:
  - name: scalastyle
    rules:
      - name: NonASCIICharacterChecker
        url:  http://www.scalastyle.org/rules-1.0.0.html#org_scalastyle_scalariform_NonASCIICharacterChecker
---

> ASCII operators (such as `->`) should be preferred over their fancy unicode equivalents (such as `→`).

# Reasons

## Not equivalent to their ASCII counterparts

While they're supposed to be equivalent, they're not, at least as far as [priority](https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#infix-operations) is concerned:
* `->` has a lower priority than `/`
* `→` has a higher priority than `/`

This makes the following code legal:

```scala mdoc
1 -> 4 / 2 // Equivalent to 1 -> (4 / 2)
```

The following code, on the other hand, isn't:

```scala mdoc:fail
1 → 4 / 2 // Equivalent to (1 → 4) / 2
```

This violates reasonable assumptions about the behaviour of unicode operators, and is an accident waiting to happen. Better to avoid them altogether and rely on [fonts with ligature support](https://github.com/tonsky/FiraCode) or [editor support](https://emacsredux.com/blog/2014/08/25/a-peek-at-emacs-24-dot-4-prettify-symbols-mode/) for fancy display.


## Soon to be deprecated

As it happens, the feature is controversial enough that it's going to be [deprecated](https://github.com/scala/scala/pull/7540) in an upcoming Scala version.


================================================
FILE: src/main/mdoc/_unsafe/array_comparison.md
================================================
---
title: Do not compare arrays with ==
layout: article
linters:
  - name: wartremover
    rules:
      - name: ArrayEquals
        url:  http://www.wartremover.org/doc/warts.html#arrayequals
  - name: scapegoat
    rules:
      - name: ArrayEquals
---

> When comparing two arrays for equality, use [`sameElements`] rather than `==`.

# Reason

`==` does not compare arrays for value equality, but for [reference equality].

This gives us the following counter-intuitive behaviour:

```scala mdoc
Array(1) == Array(1)
```

This is because [`Array`] is essentially an alias for Java's array, which implements [`equals`] as [reference equality] - only returning `true` if two variables point to the same array instance.

[`sameElements`], on the other hand, has the behaviour you'd expect:

```scala mdoc
Array(1) sameElements Array(1)
```

# Alternatives

An alternative to [`sameElements`] is calling [`deep`] on each array before comparison:

```scala mdoc
Array(1).deep == Array(1).deep
```

This is not the preferred solution because it's slightly more expensive, creating instances that will be discarded immediately.

[`Array`]:https://www.scala-lang.org/api/2.12.8/scala/Array.html
[`sameElements`]:https://www.scala-lang.org/api/2.12.8/scala/Array.html#sameElements(that:scala.collection.GenIterable[A]):Boolean
[`deep`]:https://www.scala-lang.org/api/2.12.8/scala/Array.html#deep:IndexedSeq[Any]
[`equals`]:https://docs.oracle.com/javase/8/docs/api/java/util/Objects.html#equals-java.lang.Object-java.lang.Object-
[reference equality]:../definitions/reference_equality.html


================================================
FILE: src/main/mdoc/_unsafe/avoid_null.md
================================================
---
title: Do not use null
layout: article
linters:
  - name: wartremover
    rules:
      - name: "Null"
        url:  http://www.wartremover.org/doc/warts.html#null
  - name: scapegoat
    rules:
      - name: NullAssignment
      - name: NullParameter
  - name: scalastyle
    rules:
      - name: NullChecker
        url:  http://www.scalastyle.org/rules-1.0.0.html#org_scalastyle_scalariform_NullChecker
---

> Whenever `null` seems like a good idea, use [`Option`] instead.

# Reasons

## It's not safe

As far as types are concerned, `null` is a bit of a lie:

```scala mdoc:silent
val s: String = null
```

The compiler believes `s` to be a [`String`] and will accept it wherever one is required. The compiler is, obviously, wrong:

```scala mdoc:crash
s.toLowerCase
```

Whenever you're using `null`, you're hindering the compiler's ability to prove your code incorrect.

## It's not pleasant

The existence of `null` is terribly unpleasant: it means that you can't trust any value to not be `null`. So, in theory, you'd be forced to write code like:

```scala mdoc
def concat(a: String, b: String): String = {
  if(a == null)      b
  else if(b == null) a
  else               s"$a$b"
}
```

That's a lot of boilerplate. In Scala, the general convention is that we pretend `null` does not exist and any value not wrapped in an [`Option`] must always be available. This allows us to rewrite `concat`:

```scala mdoc:reset
def concat(a: String, b: String): String = s"$a$b"
```

Just as importantly, if we were to write `concat` such that either `a` or `b` might not be set, the compiler forces us to deal with this:

```scala mdoc:reset
def concat(a: Option[String], b: Option[String]): String =
  s"${a.getOrElse("")}${b.getOrElse("")}"
```

# Exception to the rule

There exists at least one scenario in which you must use `null`: Java interop. Java being what it is, some of its APIs use `null` to mean _no value there_, and you don't have much choice but to comply.

The standard [`URI`] class, for example, expect `null` values in its constructor - if you don't have a _fragment_, say, stick `null` instead and [`URI`] will work it out.

[`Option`]:https://www.scala-lang.org/api/2.12.8/scala/Option.html
[`String`]:https://docs.oracle.com/javase/8/docs/api/java/lang/String.html
[`URI`]:https://docs.oracle.com/javase/8/docs/api/java/net/URI.html


================================================
FILE: src/main/mdoc/_unsafe/checking_empty_collection.md
================================================
---
title: Do not compute the size of a collection to check for emptiness
layout: article
linters:
  - name: scapegoat
    rules:
      - name: AvoidSizeEqualsZero
      - name: AvoidSizeNotEqualsZero
---

> When checking whether a collection is empty, use [`isEmpty`] or [`nonEmpty`] rather than the all too common `size == 0`.

# Reasons

## It's inefficient

Collections such as [`List`] require a complete traversal to compute their size. Doing so just to check whether there's at least one element is clearly more expensive than it needs to be.

To prove this point, let's create a simple benchmarking method:

```scala mdoc
def time[A](t: => A): Long = {
  val now = System.currentTimeMillis()
  t
  System.currentTimeMillis() - now
}
```

We'll also need an unreasonably large [`List`]:

```scala mdoc:silent
val list = (0 to 10000000).toList
```

We can now check that one approach is indeed far longer than the other:

```scala mdoc
time(list.isEmpty)

time(list.size == 0)
```

## It's unsafe

Some collections are infinite, and will loop forever when you try to compute their length:

[//]:I can't use mdoc here, since this will loop forever
```scala
// Don't run this.
Stream.from(1).size
```

[`isEmpty`], on the other hand, behaves sanely:

```scala mdoc
Stream.from(1).isEmpty
```

[`List`]:https://www.scala-lang.org/api/2.12.8/scala/collection/immutable/List.html
[`Stream`]:https://www.scala-lang.org/api/2.12.8/scala/collection/immutable/Stream.html
[`isEmpty`]:https://www.scala-lang.org/api/2.12.8/scala/collection/SeqLike.html#isEmpty:Boolean
[`nonEmpty`]:https://www.scala-lang.org/api/2.12.8/scala/collection/SeqLike.html#nonEmpty:Boolean


================================================
FILE: src/main/mdoc/_unsafe/custom_extractors.md
================================================
---
title: Do not return Option from custom extractors
layout: article
---

> When defining a custom extractor that happens to be [total](../definitions/total_function.html), always have a return type of [`Some`] rather than [`Option`].

# Reason

This is a bit convoluted and has to do with exhaustivity checking in pattern matching, by which I mean:

```scala mdoc:fail
def unwrap(oi: Option[Int]): Int = oi match {
  case Some(i) => i
}
```

You get a warning here because there are values of `oi` that would cause your code to fail at runtime.

A common misconception about this check is that you get a warning whenever the compiler fails to prove exhaustivity. What actually happens is slightly different: you'll get a warning whenever the compiler succeeds in proving non-exhaustivity.

The distinction is subtle, but important: when the compiler cannot find a concrete value that is not covered by a pattern match, even though it knows such a value might exist, it will not warn.

And if your custom extractor returns [`Option`], that's exactly what happens: it's telling the compiler that there might be values for which it's not defined, but it doesn't tell it *which* values. This effectively disables exhaustivity checking.

Here's a concrete example:

```scala mdoc
object ExtractSome {
  def unapply[A](s: Some[A]): Option[A] = s
}
```

Using this code, we can write the following pattern match:

```scala mdoc
def unwrap(oi: Option[Int]): Int = oi match {
  case ExtractSome(i) => i
}
```

We're not getting a warning, even though our pattern match is clearly non-exhaustive: it'll fail on [`None`].

```scala mdoc:crash
unwrap(None)
```

The presence of an extractor whose return type is [`Option`] disabled exhaustivity checking, even in the presence of concrete values that are not covered by the pattern match.

Let's change our custom extractor to return a [`Some`]:

```scala mdoc:reset
object ExtractSome {
  def unapply[A](s: Some[A]): Some[A] = s
}
```

This is a subtle difference that changes everything: [`Some`] means that our extractor will always succeed, allowing the compiler to look for further proof of non-exhaustivity (and find it):

```scala mdoc:fail
def unwrap(oi: Option[Int]): Int = oi match {
  case ExtractSome(i) => i
}
```

# Improvement

An even better rule of thumb would be to either not define custom extractors, or at least never define partial ones - pattern match exhaustivity is something that most people take for granted, and sneakily disabling it can lead to all sorts of unpleasant runtime behaviours.

[`Some`]:https://www.scala-lang.org/api/2.12.8/scala/Some.html
[`Option`]:https://www.scala-lang.org/api/2.12.8/scala/Option.html
[`None`]:https://www.scala-lang.org/api/2.12.8/scala/None$.html


================================================
FILE: src/main/mdoc/_unsafe/implicit_conversions.md
================================================
---
title: Avoid implicit conversions
layout: article
linters:
  - name: wartremover
    rules:
      - name: ImplicitConversion
        url:  http://www.wartremover.org/doc/warts.html#implicitconversion
---

> Avoid implicit conversions like the plague they are.

# Reason

Implicit conversions allow the compiler to treat values of a type as values of another type.

There's at least one set of scenarios in which this is unambiguously bad: non-[total] conversions. That is, converting an `A` to a `B` when there exists `A`s for which this conversion is impossible.

For example, [`String`] to [`Int`]:

```scala mdoc
implicit def str2int(str: String): Int = Integer.parseInt(str)
```

What this does is give the compiler a proof, as far as it's concerned, that all [`String`]s are [`Int`]s and he can accept the former where the later is expected.

Our proof is unfortunately flawed, and will result in runtime failures:

```scala mdoc:crash
"foobar" / 2
```

# Exceptions to the rule

[Total][total] conversions are more palatable - they shouldn't result in runtime failures, at least.

One common scenario is adding methods to an existing type:

```scala mdoc
implicit class ExtendedInt(i: Int) {
  def add1: Int = i + 1
}
```

Which lets us run:

```scala mdoc
1.add1
```

In this scenario, all [`Int`]s can be converted to `ExtendedInt`: the conversion is [total] and cannot result in runtime failure.

[`Int`]:https://www.scala-lang.org/api/2.12.8/scala/Int.html
[`String`]:https://docs.oracle.com/javase/8/docs/api/java/lang/String.html
[total]:../definitions/total_function.html


================================================
FILE: src/main/mdoc/_unsafe/index.md
================================================
---
layout: section
---

We're now tackling parts of Scala that are actively unsafe to use: misusing them will cause programs not to terminate, or to break in truly incomprehensible ways.

Readers should pay attention to these rules, as in my experience even advanced developers sometimes fail to heed some of them.


================================================
FILE: src/main/mdoc/_unsafe/recursion.md
================================================
---
title: Make recursive functions tail-recursive
layout: article
linters:
  - name: wartremover
    rules:
      - name: Recursion
        url:  http://www.wartremover.org/doc/warts.html#recursion
---

> When writing [recursive] functions, consider making them [tail recursive].

# Reason

Non-tail recursive functions that call themselves too often end up throwing [`StackOverflowError`] at runtime.

Here's a naïve recursive function used to compute the sum of a [`List[Int]`][`List`]:

```scala mdoc
def sum(is: List[Int]): Int = is match {
  case h :: t => h + sum(t)
  case _      => 0
}
```

This implementation suffers from a major flaw: on long enough lists, it will cause a runtime exception.

[//]: I cannot use mdoc here since there's no way I could find to truncate the output, and the stack trace is *large*.
```scala
sum(List.range(1, 30000))
// java.lang.StackOverflowError
//   at .sum(<console>:12)
//   at .sum(<console>:13)
//   at .sum(<console>:13)
//   [...]
```

What happens is that, for each recursive call, the call's context must be stored on the stack - and when a recursive function calls itself a lot, you get a stack overflow exception.

When the compiler spots a [tail recursive] function, however, it knows to optimise it by essentially turning it into a `while` loops - no more recursive calls, no more frames pushed on the stack.

Here's our `sum` function, but implemented tail recursively:

```scala mdoc:reset
def sum(is: List[Int]): Int = {

  // `loop` i our tail recursive function, keeping a running sum
  // in `acc`
  def loop(cur: List[Int], acc: Int): Int = cur match {
    case h :: t => loop(t, acc + h)
    case _      => acc
  }

  loop(is, 0)
}
```

And as you can see, this is now safe:

```scala mdoc
sum(List.range(1, 30000))
```

# Exceptions to the rule

Tail recursion is a desirable property, but not an absolute requirement.

There are scenarios where "normal" recursion is more appropriate. A fairly standard example is tree traversal:
* the recursion is bounded to the height of the tree, so there's no real risk of a [`StackOverflowError`].
* tail-recursive functions for tree exploration are far more complicated than non tail-recursive ones.

As is often the case, this rule is more of a default decision, to be overruled when you need to.



[recursive]:../definitions/recursion.html
[tail recursive]:../definitions/tail_recursion.html
[`List`]:https://www.scala-lang.org/api/2.12.8/scala/collection/immutable/List.html
[`StackOverflowError`]:https://docs.oracle.com/javase/8/docs/api/java/lang/StackOverflowError.html


================================================
FILE: src/main/mdoc/_unsafe/structural_types.md
================================================
---
title: Avoid structural types
layout: article
linters:
  - name: scalastyle
    rules:
      - name: StructuralTypeChecker
        url:  http://www.scalastyle.org/rules-1.0.0.html#org_scalastyle_scalariform_StructuralTypeChecker
---

> When a structural type seems like a good solution to a problem, consider using a [type class] instead.

# Reasons

## Structural types are "slow"

Structural types rely on runtime reflection. Since reflection pushes some type work to the runtime, it's inherently slower than solutions where all this work is done at compile time.

Note that this is unlikely to be a bottleneck except in very specific use cases, and shouldn't be enough to discourage people in scenarios where structural types are an elegant solution.

## Structural types are not always supported

On the other hand, the fact that structural types might fail at runtime for reasons entirely outside of the code author's control probably is a good reason not to use them.

When running on the JVM (as opposed to the scala.js or native backend, say), there's one scenario where structural types will break: reflection is controlled by whatever [`SecurityManager`] is running. The default one is quite lenient, but it's possible to configure one that bans reflection altogether.

This will break Scala code in ways that are impossible to validate statically.

## Type classes can express the same thing

Let's imagine that we want the following behaviour:

```scala mdoc
def add1(x: { def get: Int }): Int = 1 + x.get
```

`add1` takes any object that has a `get` method, calls it, adds 1 to it and returns that.

For example:

```scala mdoc
final case class Wrapper(i: Int) {
  def get: Int = i
}
```

`Wrapper` has a `get` method, and we can call `add1` on it:

```scala mdoc
add1(Wrapper(1))
```

It is, however, possible to express the notion of _has a get: Int_ method as a [type class]:

```scala mdoc
trait HasGet[A] {
  def get(a: A): Int
}

// add1 now works with any type on which value you can call get
def add1[A](a: A)(implicit hga: HasGet[A]): Int = hga.get(a) + 1
```

Declaring an instance for `Wrapper` is straightforward:

```scala mdoc:silent
implicit val wrap: HasGet[Wrapper] = new HasGet[Wrapper] {
  def get(a: Wrapper) = a.i
}
```

And we can now call `add1` like we wanted:

```scala mdoc
add1(Wrapper(1))
```

This solution is admitedly more verbose than the structural type alternative. It's also entirely statically verified, cannot fail at runtime, and is probably also slightly faster.

[`SecurityManager`]:https://docs.oracle.com/javase/7/docs/api/java/lang/SecurityManager.html
[type class]:../definitions/type_class.html


================================================
FILE: src/main/mdoc/_unsafe/tail_recursion.md
================================================
---
title: Mark tail-recursive functions as such
layout: article
---

> Always annotate your [tail-recursive] function with [`@annotation.tailrec`].

# Reason

This will let the compiler know that you expect your function to be [tail-recursive], and allow compilation to fail should it not be.

This is important, because there are scenarios where you'd expect a function to be [tail-recursive] but it really isn't. Take, for example:

```scala mdoc
class Foo {
  def sum(cur: List[Int], acc: Int): Int = cur match {
    case h :: t => sum(t, acc + h)
    case _      => acc
  }
}
```

This looks [tail-recursive] - `sum` calls itself in tail position, after all. Turns out, however, that it's not:

```scala mdoc:fail:reset
class Foo {
  @annotation.tailrec
  def sum(cur: List[Int], acc: Int): Int = cur match {
    case h :: t => sum(t, acc + h)
    case _      => acc
  }
}
```

Thanks to that error message, we can fix the problem and make `sum` propery [tail-recursive]:

```scala mdoc:reset
class Foo {
  @annotation.tailrec
  final def sum(cur: List[Int], acc: Int): Int = cur match {
    case h :: t => sum(t, acc + h)
    case _      => acc
  }
}
```

[recursive]:../definitions/recursion.html
[tail-recursive]:../definitions/tail_recursion.html
[`@annotation.tailrec`]:https://www.scala-lang.org/api/2.12.8/scala/annotation/tailrec.html


================================================
FILE: src/main/mdoc/_warming_up/checking_for_nan.md
================================================
---
title: Use isNaN when checking for NaN
layout: article
linters:
  - name: linter
    rules:
      - name: UseIsNanNotNanComparison
        url:  https://github.com/HairyFotr/linter/blob/master/src/test/scala/LinterPluginTest.scala#L1930
  - name: scapegoat
    rules:
      - name: NanComparison
---

> When checking whether a number is [`NaN`], use [`isNaN`] rather than `== NaN`.

Note that, unlike most rules here, this one is not Scala specific. `NaN` equality behaves unintuitively everywhere `NaN` exists.

# Reason

By [specification](https://en.wikipedia.org/wiki/IEEE_754), [`NaN`] is not equal to anything, not even itself:

```scala mdoc
Double.NaN == Double.NaN
```

Use [`isNaN`] instead, which is meant for just this task:

```scala mdoc
Double.NaN.isNaN
```

# Exception to the rule

There's one scenario in which you shouldn't use [`isNaN`]: if you're working with a lot of numbers and need to manually validate each one of them. [`isNaN`] can be a bit slow - it's been much improved in 2.12+, but still has a small cost.

If you identify this as a bottleneck, you always have the option of being clever. The two following methods produce the same result, but the second one is faster:

```scala mdoc
def slowFilterNaN(ds: Seq[Double]): Seq[Double] = ds.filter(d => !d.isNaN)

def fastFilterNaN(ds: Seq[Double]): Seq[Double] = ds.filter(d => d == d)
```

Note that this is an optimisation, and one that is sure to mystify some readers. It should only be used when a bottleneck is identified, as the runtime gain is otherwise guaranteed to be lower than the human cost of explaining it over and over again.

[`NaN`]:https://www.scala-lang.org/api/2.12.8/scala/Double$.html#NaN:Double(NaN)
[`isNaN`]:https://www.scala-lang.org/api/2.12.8/scala/Double.html#isNaN:Boolean


================================================
FILE: src/main/mdoc/_warming_up/checking_for_odd.md
================================================
---
title: Compare remainder to 0 when checking for oddness
layout: article
linters:
  - name: scapegoat
    rules:
      - name: BrokenOddness
---

> When checking whether a number is odd, always use `x % 2 != 0` rather than the more common `x % 2 == 1`.

Note that, unlike most rules here, this one is not Scala specific.

# Reason

There are odd numbers whose division by 2 has a remainder that's not 1:

```scala mdoc
-3 % 2
```

The [mathematical definition](https://en.wikipedia.org/wiki/Parity_(mathematics)) of odd and even numbers is:
* an even number is one whose division by 2 has no remainder
* an odd number is not even

This suggests the following implementations:

```scala mdoc
def isEven(i: Int): Boolean = i % 2 == 0

def isOdd(i: Int): Boolean = i % 2 != 0
```

And, indeed:

```scala mdoc
-3 % 2 != 0
```


================================================
FILE: src/main/mdoc/_warming_up/index.md
================================================
---
layout: section
---

This first section presents a few simple, non-controversial rules, with the purpose of easing the reader into the site's format.

Most of these rules are not Scala specific and probably familiar to a lot of readers already, but they should not be skipped - ignoring them caused me an embarrassing number of afternoons spent looking for the cause of behaviours I would have sworn could not possibly happen.


================================================
FILE: src/main/mdoc/_warming_up/numeric_literals.md
================================================
---
title: Use upper case numeric literal suffixes
layout: article
linters:
  - name: scalastyle
    rules:
      - name: UppercaseLChecker
        url:  http://www.scalastyle.org/rules-1.0.0.html#org_scalastyle_scalariform_UppercaseLChecker
---

> When declaring literal numbers such as [`Long`] or [`Float`], use upper case suffix. For example, prefer `2L` to `2l`.

# Reason

Depending on the font and the syntax highlighting scheme, some letters look a lot like numbers. In some configurations, for example, `l` (lower case `L`) and `1` (one) are basically indistinguishable. Github, for instance, while not the worst offender, isn't doing a great job there.

To the casual reader, the following has a fair chance of looking like a list of [`Int`]s, but a [`Long`] sneaked in:

```scala mdoc:silent
List(1, 11, 111, 111l, 11111, 11111, 11111)
```

Using upper-case letters makes this more obvious:

```scala mdoc:silent
List(1, 11, 111, 111L, 11111, 11111, 11111)
```

[`Long`]:https://www.scala-lang.org/api/2.12.8/scala/Long.html
[`Float`]:https://www.scala-lang.org/api/2.12.8/scala/Float.html
[`Int`]:https://www.scala-lang.org/api/2.12.8/scala/Int.html


================================================
FILE: src/main/mdoc/index.md
================================================
---
layout: index
---

# Foreword

I often find myself, both professionaly and otherwise, having to explain bits of Scala to newcomers to the language (but usually not new to programming).

Something that's becoming increasingly obvious is that Scala developers follow a certain set of unspoken rules without really thinking about them, and never really explain them to beginners. This is not helping Scala's reputation as a hard to learn language, which is unfortunate - it's a language I enjoy and wish more people would learn.

This site is meant to address that, by listing and explaining all these rules I wish someone'd told me about when I was learning the language.

Comments, suggestions, ... are welcome! I'm clearly not the best Scala developer out there and might have gotten things wrong, or right for the wrong reasons. If you see areas that could be improved on, feel free to open an issue!


================================================
FILE: src/site/_config.yml
================================================
name:        Scala Best Practices
markdown:    kramdown
highlighter: rouge
baseurl:     /scala-best-practices

collections:
  warming_up:
    output:   true
    title:    Warming up
    sequence: 1
  tricky_behaviours:
    output:   true
    title:    Tricky behaviours
    sequence: 2
  unsafe:
    output:   true
    title:    Unsafe patterns
    sequence: 3
  partial_functions:
    output:   true
    title:    Partial functions
    sequence: 4
  binary_compat:
    output:   true
    title:    Binary compatibility
    sequence: 5
  referential_transparency:
    output:   true
    title:    Referential transparency
    sequence: 6
  adts:
    output:   true
    title:    ADTs
    sequence: 7
  oop:
    output:   true
    title:    OOP
    sequence: 8
  definitions:
    output: true

kramdown:
  input:     GFM
  hard_wrap: false

compress_html:
  clippings: all
  comments:  ["<!-- ", " -->"]
  endings:   all


================================================
FILE: src/site/_includes/footer.html
================================================

<div id="footer">
  <hr>

  <p class="wrapper">
    This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.
  </p>
</div>


================================================
FILE: src/site/_includes/header.html
================================================
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{{ site.name }}{% if page.title %} - {{ page.title }}{% endif %}</title>

    <link rel="stylesheet" href="{{ site.baseurl }}/css/styles.css">
    <link  rel="shortcut icon" href="{{ site.baseurl }}/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <!--[if lt IE 9]>
        <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
         </head>
  <body>
    <div id="navbar">
      <div class="wrapper">
        <span class="external"><a title="Issues" href="https://github.com/nrinaudo/scala-best-practices/issues"><i class="fa fa-bug fa-lg"></i></a></span>
        <span class="external"><a title="Github" href="https://github.com/nrinaudo/scala-best-practices"><i class="fa-brands fa-github fa-lg"></i></a></span>
        <span class="external"><a title="Twitter" href="https://twitter.com/nicolasrinaudo"><i class="fa-brands fa-twitter fa-lg"></i></a></span>
        <span class="external"><a title="Mastodon" rel="me" href="https://functional.cafe/@NicolasRinaudo"><i class="fa-brands fa-mastodon fa-lg"></i></a></span>

        <span class="internal"><a title="Home" href="{{ site.baseurl }}/">Best Practices</a></span>
        <!--<span class="internal"><a title="Home" href="{{ site.baseurl }}/"><i class="fa fa-home fa-lg"></i></a></span> -->
      </div>
    </div>


================================================
FILE: src/site/_includes/linters.html
================================================
<h1>Checked by</h1>
{% if include.linters %}
<table>
  <thead>
    <tr>
      <th>Linter</th>
      <th>Rule</th>
    </tr>
  </thead>

  <tbody>
    {% assign sorted_linters = include.linters | sort: "name" %}
    {% for linter in sorted_linters %}
    {% case linter.name %}
    {% when 'wartremover' %}
    {% assign linter_name = 'WartRemover' %}
    {% assign linter_url = 'http://www.wartremover.org/' %}
    {% when 'scapegoat' %}
    {% assign linter_name = 'Scapegoat' %}
    {% assign linter_url = 'https://github.com/sksamuel/scapegoat' %}
    {% when 'linter' %}
    {% assign linter_name = 'Scala Linter' %}
    {% assign linter_url = 'https://github.com/HairyFotr/linter' %}
    {% when 'scalastyle' %}
    {% assign linter_name = 'Scalastyle' %}
    {% assign linter_url = 'http://www.scalastyle.org/' %}
    {% else %}
    {% assign linter_url = false %}
    {% endcase %}
    <tr>
      <td>
        {% if linter_url %}
        <a href="{{ linter_url }}">{{ linter_name }}</a>
        {% else %}
        {{ linter_name }}
        {% endif %}
      </td>
      <td>
        <ul>
          {% for rule in linter.rules %}
          <li>
            {% if rule.url %}
            <a href="{{ rule.url }}">{{ rule.name }}</a>
            {% else %}
            {{ rule.name }}
            {% endif %}
          </li>
          {% endfor %}
        </ul>
      </td>
    </tr>
    {% endfor %}
  </tbody>
</table>
{% else %}
This rule is not checked by any linter that I know of.
{% endif %}


================================================
FILE: src/site/_includes/toc.html
================================================
{% assign sorted_pages = include.collection | sort: "title" %}
<ul>
{% for x in sorted_pages %}
{% if x.title != "Index" %}
<li>
{% if x.status == "wip" %}
<i>{{ x.title }} (WIP)</i>
{% else %}
<a href="{{ site.baseurl }}{{ x.url }}">{{ x.title }}</a>
{% endif %}
</li>
{% endif %}
{% endfor %}
</ul>


================================================
FILE: src/site/_layouts/article.html
================================================
---
layout: compress
---
{% include header.html %}
<div class="wrapper">
    {% if page.title %}<h1>{{ page.title }}</h1>{% endif %}
    {{ content }}

    {% include linters.html linters=page.linters %}
</div>

</body>
</html>


================================================
FILE: src/site/_layouts/compress.html
================================================
---
# Jekyll layout that compresses HTML
# v3.0.4
# http://jch.penibelst.de/
# © 2014–2015 Anatol Broder
# MIT License
---

{% capture _LINE_FEED %}
{% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}</{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "<!-- -->" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "<pre" %}{% assign _content = "" %}{% for _pre_before in _pre_befores %}{% assign _pres = _pre_before | split: "</pre>" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "</pre>" %}<pre{{ _pres.first }}</pre>{% endif %}{% unless _pre_before contains "</pre>" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " <e;<e; </e>;</e>;</e> ;</e>" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %} <table id="compress_html_profile_{{ site.time | date: "%Y%m%d" }}" class="compress_html_profile"> <thead> <tr> <td>Step <td>Bytes <tbody> <tr> <td>raw <td>{{ content | size }}{% if _profile_endings %} <tr> <td>endings <td>{{ _profile_endings }}{% endif %}{% if _profile_startings %} <tr> <td>startings <td>{{ _profile_startings }}{% endif %}{% if _profile_comments %} <tr> <td>comments <td>{{ _profile_comments }}{% endif %}{% if _profile_collapse %} <tr> <td>collapse <td>{{ _profile_collapse }}{% endif %}{% if _profile_clippings %} <tr> <td>clippings <td>{{ _profile_clippings }}{% endif %} </table>{% endif %}{% endif %}


================================================
FILE: src/site/_layouts/definition.html
================================================
---
layout: compress
---
{% include header.html %}
<div class="wrapper">
    {% if page.title %}<h1>{{ page.title }}</h1>{% endif %}
    {{ content }}

</div>

</body>
</html>


================================================
FILE: src/site/_layouts/index.html
================================================
---
layout: compress
---
{% include header.html %}
<div class="wrapper index">
  {{ content }}

  <h1>Table of Contents</h1>

{% assign cs = site.collections | sort: 'sequence' %}
{% for c in cs %}
{% if c.title %}
<h2><a href="{{ site.baseurl }}/{{ c.label }}">{{ c.title }}</a></h2>
{% include toc.html collection=c.docs %}
{% endif %}
{% endfor %}

</div>

</body>
</html>


================================================
FILE: src/site/_layouts/section.html
================================================
---
layout: compress
---
{% include header.html %}

{% for c in site.collections %}
{% if c.label == page.collection %}
{% assign col = c %}
{% endif %}
{% endfor %}


<div class="wrapper">

  <h1>{{ col.title }}</h1>
  {{ content }}

  <h1>Content</h1>

{% include toc.html collection=col.docs %}

</div>

</body>
</html>


================================================
FILE: src/site/css/fira_code/fira_code.css
================================================
@font-face{
    font-family: 'Fira Code';
    src: url('woff2/FiraCode-Light.woff2') format('woff2'),
         url('woff/FiraCode-Light.woff') format('woff');
    font-weight: 300;
    font-style: normal;
}

@font-face{
    font-family: 'Fira Code';
    src: url('woff2/FiraCode-Regular.woff2') format('woff2'),
         url('woff/FiraCode-Regular.woff') format('woff');
    font-weight: 400;
    font-style: normal;
}

@font-face{
    font-family: 'Fira Code';
    src: url('woff2/FiraCode-Medium.woff2') format('woff2'),
         url('woff/FiraCode-Medium.woff') format('woff');
    font-weight: 500;
    font-style: normal;
}

@font-face{
    font-family: 'Fira Code';
    src: url('woff2/FiraCode-Bold.woff2') format('woff2'),
         url('woff/FiraCode-Bold.woff') format('woff');
    font-weight: 700;
    font-style: normal;
}


================================================
FILE: src/site/css/fontawesome/font-awesome.css
================================================
/*!
 * Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com
 * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
 * Copyright 2022 Fonticons, Inc.
 */
.fa {
  font-family: var(--fa-style-family, "Font Awesome 6 Free");
  font-weight: var(--fa-style, 900)
}

.fa,
.fa-brands,
.fa-classic,
.fa-regular,
.fa-sharp,
.fa-solid,
.fab,
.far,
.fas {
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  display: var(--fa-display, inline-block);
  font-style: normal;
  font-variant: normal;
  line-height: 1;
  text-rendering: auto
}

.fa-classic,
.fa-regular,
.fa-solid,
.far,
.fas {
  font-family: "Font Awesome 6 Free"
}

.fa-brands,
.fab {
  font-family: "Font Awesome 6 Brands"
}

.fa-1x {
  font-size: 1em
}

.fa-2x {
  font-size: 2em
}

.fa-3x {
  font-size: 3em
}

.fa-4x {
  font-size: 4em
}

.fa-5x {
  font-size: 5em
}

.fa-6x {
  font-size: 6em
}

.fa-7x {
  font-size: 7em
}

.fa-8x {
  font-size: 8em
}

.fa-9x {
  font-size: 9em
}

.fa-10x {
  font-size: 10em
}

.fa-2xs {
  font-size: .625em;
  line-height: .1em;
  vertical-align: .225em
}

.fa-xs {
  font-size: .75em;
  line-height: .08333em;
  vertical-align: .125em
}

.fa-sm {
  font-size: .875em;
  line-height: .07143em;
  vertical-align: .05357em
}

.fa-lg {
  font-size: 1.25em;
  line-height: .05em;
  vertical-align: -.075em
}

.fa-xl {
  font-size: 1.5em;
  line-height: .04167em;
  vertical-align: -.125em
}

.fa-2xl {
  font-size: 2em;
  line-height: .03125em;
  vertical-align: -.1875em
}

.fa-fw {
  text-align: center;
  width: 1.25em
}

.fa-ul {
  list-style-type: none;
  margin-left: var(--fa-li-margin, 2.5em);
  padding-left: 0
}

.fa-ul>li {
  position: relative
}

.fa-li {
  left: calc(var(--fa-li-width, 2em)*-1);
  position: absolute;
  text-align: center;
  width: var(--fa-li-width, 2em);
  line-height: inherit
}

.fa-border {
  border-radius: var(--fa-border-radius, .1em);
  border: var(--fa-border-width, .08em) var(--fa-border-style, solid) var(--fa-border-color, #eee);
  padding: var(--fa-border-padding, .2em .25em .15em)
}

.fa-pull-left {
  float: left;
  margin-right: var(--fa-pull-margin, .3em)
}

.fa-pull-right {
  float: right;
  margin-left: var(--fa-pull-margin, .3em)
}

.fa-beat {
  -webkit-animation-name: fa-beat;
  animation-name: fa-beat;
  -webkit-animation-delay: var(--fa-animation-delay, 0s);
  animation-delay: var(--fa-animation-delay, 0s);
  -webkit-animation-direction: var(--fa-animation-direction, normal);
  animation-direction: var(--fa-animation-direction, normal);
  -webkit-animation-duration: var(--fa-animation-duration, 1s);
  animation-duration: var(--fa-animation-duration, 1s);
  -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
  animation-timing-function: var(--fa-animation-timing, ease-in-out)
}

.fa-bounce {
  -webkit-animation-name: fa-bounce;
  animation-name: fa-bounce;
  -webkit-animation-delay: var(--fa-animation-delay, 0s);
  animation-delay: var(--fa-animation-delay, 0s);
  -webkit-animation-direction: var(--fa-animation-direction, normal);
  animation-direction: var(--fa-animation-direction, normal);
  -webkit-animation-duration: var(--fa-animation-duration, 1s);
  animation-duration: var(--fa-animation-duration, 1s);
  -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(.28, .84, .42, 1));
  animation-timing-function: var(--fa-animation-timing, cubic-bezier(.28, .84, .42, 1))
}

.fa-fade {
  -webkit-animation-name: fa-fade;
  animation-name: fa-fade;
  -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(.4, 0, .6, 1));
  animation-timing-function: var(--fa-animation-timing, cubic-bezier(.4, 0, .6, 1))
}

.fa-beat-fade,
.fa-fade {
  -webkit-animation-delay: var(--fa-animation-delay, 0s);
  animation-delay: var(--fa-animation-delay, 0s);
  -webkit-animation-direction: var(--fa-animation-direction, normal);
  animation-direction: var(--fa-animation-direction, normal);
  -webkit-animation-duration: var(--fa-animation-duration, 1s);
  animation-duration: var(--fa-animation-duration, 1s)
}

.fa-beat-fade {
  -webkit-animation-name: fa-beat-fade;
  animation-name: fa-beat-fade;
  -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(.4, 0, .6, 1));
  animation-timing-function: var(--fa-animation-timing, cubic-bezier(.4, 0, .6, 1))
}

.fa-flip {
  -webkit-animation-name: fa-flip;
  animation-name: fa-flip;
  -webkit-animation-delay: var(--fa-animation-delay, 0s);
  animation-delay: var(--fa-animation-delay, 0s);
  -webkit-animation-direction: var(--fa-animation-direction, normal);
  animation-direction: var(--fa-animation-direction, normal);
  -webkit-animation-duration: var(--fa-animation-duration, 1s);
  animation-duration: var(--fa-animation-duration, 1s);
  -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
  animation-timing-function: var(--fa-animation-timing, ease-in-out)
}

.fa-shake {
  -webkit-animation-name: fa-shake;
  animation-name: fa-shake;
  -webkit-animation-duration: var(--fa-animation-duration, 1s);
  animation-duration: var(--fa-animation-duration, 1s);
  -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  -webkit-animation-timing-function: var(--fa-animation-timing, linear);
  animation-timing-function: var(--fa-animation-timing, linear)
}

.fa-shake,
.fa-spin {
  -webkit-animation-delay: var(--fa-animation-delay, 0s);
  animation-delay: var(--fa-animation-delay, 0s);
  -webkit-animation-direction: var(--fa-animation-direction, normal);
  animation-direction: var(--fa-animation-direction, normal)
}

.fa-spin {
  -webkit-animation-name: fa-spin;
  animation-name: fa-spin;
  -webkit-animation-duration: var(--fa-animation-duration, 2s);
  animation-duration: var(--fa-animation-duration, 2s);
  -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  -webkit-animation-timing-function: var(--fa-animation-timing, linear);
  animation-timing-function: var(--fa-animation-timing, linear)
}

.fa-spin-reverse {
  --fa-animation-direction: reverse
}

.fa-pulse,
.fa-spin-pulse {
  -webkit-animation-name: fa-spin;
  animation-name: fa-spin;
  -webkit-animation-direction: var(--fa-animation-direction, normal);
  animation-direction: var(--fa-animation-direction, normal);
  -webkit-animation-duration: var(--fa-animation-duration, 1s);
  animation-duration: var(--fa-animation-duration, 1s);
  -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  animation-iteration-count: var(--fa-animation-iteration-count, infinite);
  -webkit-animation-timing-function: var(--fa-animation-timing, steps(8));
  animation-timing-function: var(--fa-animation-timing, steps(8))
}

@media (prefers-reduced-motion:reduce) {

  .fa-beat,
  .fa-beat-fade,
  .fa-bounce,
  .fa-fade,
  .fa-flip,
  .fa-pulse,
  .fa-shake,
  .fa-spin,
  .fa-spin-pulse {
    -webkit-animation-delay: -1ms;
    animation-delay: -1ms;
    -webkit-animation-duration: 1ms;
    animation-duration: 1ms;
    -webkit-animation-iteration-count: 1;
    animation-iteration-count: 1;
    transition-delay: 0s;
    transition-duration: 0s
  }
}

@-webkit-keyframes fa-beat {

  0%,
  90% {
    -webkit-transform: scale(1);
    transform: scale(1)
  }

  45% {
    -webkit-transform: scale(var(--fa-beat-scale, 1.25));
    transform: scale(var(--fa-beat-scale, 1.25))
  }
}

@keyframes fa-beat {

  0%,
  90% {
    -webkit-transform: scale(1);
    transform: scale(1)
  }

  45% {
    -webkit-transform: scale(var(--fa-beat-scale, 1.25));
    transform: scale(var(--fa-beat-scale, 1.25))
  }
}

@-webkit-keyframes fa-bounce {
  0% {
    -webkit-transform: scale(1) translateY(0);
    transform: scale(1) translateY(0)
  }

  10% {
    -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, .9)) translateY(0);
    transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, .9)) translateY(0)
  }

  30% {
    -webkit-transform: scale(var(--fa-bounce-jump-scale-x, .9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -.5em));
    transform: scale(var(--fa-bounce-jump-scale-x, .9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -.5em))
  }

  50% {
    -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, .95)) translateY(0);
    transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, .95)) translateY(0)
  }

  57% {
    -webkit-transform: scale(1) translateY(var(--fa-bounce-rebound, -.125em));
    transform: scale(1) translateY(var(--fa-bounce-rebound, -.125em))
  }

  64% {
    -webkit-transform: scale(1) translateY(0);
    transform: scale(1) translateY(0)
  }

  to {
    -webkit-transform: scale(1) translateY(0);
    transform: scale(1) translateY(0)
  }
}

@keyframes fa-bounce {
  0% {
    -webkit-transform: scale(1) translateY(0);
    transform: scale(1) translateY(0)
  }

  10% {
    -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, .9)) translateY(0);
    transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, .9)) translateY(0)
  }

  30% {
    -webkit-transform: scale(var(--fa-bounce-jump-scale-x, .9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -.5em));
    transform: scale(var(--fa-bounce-jump-scale-x, .9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -.5em))
  }

  50% {
    -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, .95)) translateY(0);
    transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, .95)) translateY(0)
  }

  57% {
    -webkit-transform: scale(1) translateY(var(--fa-bounce-rebound, -.125em));
    transform: scale(1) translateY(var(--fa-bounce-rebound, -.125em))
  }

  64% {
    -webkit-transform: scale(1) translateY(0);
    transform: scale(1) translateY(0)
  }

  to {
    -webkit-transform: scale(1) translateY(0);
    transform: scale(1) translateY(0)
  }
}

@-webkit-keyframes fa-fade {
  50% {
    opacity: var(--fa-fade-opacity, .4)
  }
}

@keyframes fa-fade {
  50% {
    opacity: var(--fa-fade-opacity, .4)
  }
}

@-webkit-keyframes fa-beat-fade {

  0%,
  to {
    opacity: var(--fa-beat-fade-opacity, .4);
    -webkit-transform: scale(1);
    transform: scale(1)
  }

  50% {
    opacity: 1;
    -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
    transform: scale(var(--fa-beat-fade-scale, 1.125))
  }
}

@keyframes fa-beat-fade {

  0%,
  to {
    opacity: var(--fa-beat-fade-opacity, .4);
    -webkit-transform: scale(1);
    transform: scale(1)
  }

  50% {
    opacity: 1;
    -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
    transform: scale(var(--fa-beat-fade-scale, 1.125))
  }
}

@-webkit-keyframes fa-flip {
  50% {
    -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
    transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg))
  }
}

@keyframes fa-flip {
  50% {
    -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
    transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg))
  }
}

@-webkit-keyframes fa-shake {
  0% {
    -webkit-transform: rotate(-15deg);
    transform: rotate(-15deg)
  }

  4% {
    -webkit-transform: rotate(15deg);
    transform: rotate(15deg)
  }

  8%,
  24% {
    -webkit-transform: rotate(-18deg);
    transform: rotate(-18deg)
  }

  12%,
  28% {
    -webkit-transform: rotate(18deg);
    transform: rotate(18deg)
  }

  16% {
    -webkit-transform: rotate(-22deg);
    transform: rotate(-22deg)
  }

  20% {
    -webkit-transform: rotate(22deg);
    transform: rotate(22deg)
  }

  32% {
    -webkit-transform: rotate(-12deg);
    transform: rotate(-12deg)
  }

  36% {
    -webkit-transform: rotate(12deg);
    transform: rotate(12deg)
  }

  40%,
  to {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg)
  }
}

@keyframes fa-shake {
  0% {
    -webkit-transform: rotate(-15deg);
    transform: rotate(-15deg)
  }

  4% {
    -webkit-transform: rotate(15deg);
    transform: rotate(15deg)
  }

  8%,
  24% {
    -webkit-transform: rotate(-18deg);
    transform: rotate(-18deg)
  }

  12%,
  28% {
    -webkit-transform: rotate(18deg);
    transform: rotate(18deg)
  }

  16% {
    -webkit-transform: rotate(-22deg);
    transform: rotate(-22deg)
  }

  20% {
    -webkit-transform: rotate(22deg);
    transform: rotate(22deg)
  }

  32% {
    -webkit-transform: rotate(-12deg);
    transform: rotate(-12deg)
  }

  36% {
    -webkit-transform: rotate(12deg);
    transform: rotate(12deg)
  }

  40%,
  to {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg)
  }
}

@-webkit-keyframes fa-spin {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg)
  }

  to {
    -webkit-transform: rotate(1turn);
    transform: rotate(1turn)
  }
}

@keyframes fa-spin {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg)
  }

  to {
    -webkit-transform: rotate(1turn);
    transform: rotate(1turn)
  }
}

.fa-rotate-90 {
  -webkit-transform: rotate(90deg);
  transform: rotate(90deg)
}

.fa-rotate-180 {
  -webkit-transform: rotate(180deg);
  transform: rotate(180deg)
}

.fa-rotate-270 {
  -webkit-transform: rotate(270deg);
  transform: rotate(270deg)
}

.fa-flip-horizontal {
  -webkit-transform: scaleX(-1);
  transform: scaleX(-1)
}

.fa-flip-vertical {
  -webkit-transform: scaleY(-1);
  transform: scaleY(-1)
}

.fa-flip-both,
.fa-flip-horizontal.fa-flip-vertical {
  -webkit-transform: scale(-1);
  transform: scale(-1)
}

.fa-rotate-by {
  -webkit-transform: rotate(var(--fa-rotate-angle, none));
  transform: rotate(var(--fa-rotate-angle, none))
}

.fa-stack {
  display: inline-block;
  height: 2em;
  line-height: 2em;
  position: relative;
  vertical-align: middle;
  width: 2.5em
}

.fa-stack-1x,
.fa-stack-2x {
  left: 0;
  position: absolute;
  text-align: center;
  width: 100%;
  z-index: var(--fa-stack-z-index, auto)
}

.fa-stack-1x {
  line-height: inherit
}

.fa-stack-2x {
  font-size: 2em
}

.fa-inverse {
  color: var(--fa-inverse, #fff)
}

.fa-0:before {
  content: "\30"
}

.fa-1:before {
  content: "\31"
}

.fa-2:before {
  content: "\32"
}

.fa-3:before {
  content: "\33"
}

.fa-4:before {
  content: "\34"
}

.fa-5:before {
  content: "\35"
}

.fa-6:before {
  content: "\36"
}

.fa-7:before {
  content: "\37"
}

.fa-8:before {
  content: "\38"
}

.fa-9:before {
  content: "\39"
}

.fa-fill-drip:before {
  content: "\f576"
}

.fa-arrows-to-circle:before {
  content: "\e4bd"
}

.fa-chevron-circle-right:before,
.fa-circle-chevron-right:before {
  content: "\f138"
}

.fa-at:before {
  content: "\40"
}

.fa-trash-alt:before,
.fa-trash-can:before {
  content: "\f2ed"
}

.fa-text-height:before {
  content: "\f034"
}

.fa-user-times:before,
.fa-user-xmark:before {
  content: "\f235"
}

.fa-stethoscope:before {
  content: "\f0f1"
}

.fa-comment-alt:before,
.fa-message:before {
  content: "\f27a"
}

.fa-info:before {
  content: "\f129"
}

.fa-compress-alt:before,
.fa-down-left-and-up-right-to-center:before {
  content: "\f422"
}

.fa-explosion:before {
  content: "\e4e9"
}

.fa-file-alt:before,
.fa-file-lines:before,
.fa-file-text:before {
  content: "\f15c"
}

.fa-wave-square:before {
  content: "\f83e"
}

.fa-ring:before {
  content: "\f70b"
}

.fa-building-un:before {
  content: "\e4d9"
}

.fa-dice-three:before {
  content: "\f527"
}

.fa-calendar-alt:before,
.fa-calendar-days:before {
  content: "\f073"
}

.fa-anchor-circle-check:before {
  content: "\e4aa"
}

.fa-building-circle-arrow-right:before {
  content: "\e4d1"
}

.fa-volleyball-ball:before,
.fa-volleyball:before {
  content: "\f45f"
}

.fa-arrows-up-to-line:before {
  content: "\e4c2"
}

.fa-sort-desc:before,
.fa-sort-down:before {
  content: "\f0dd"
}

.fa-circle-minus:before,
.fa-minus-circle:before {
  content: "\f056"
}

.fa-door-open:before {
  content: "\f52b"
}

.fa-right-from-bracket:before,
.fa-sign-out-alt:before {
  content: "\f2f5"
}

.fa-atom:before {
  content: "\f5d2"
}

.fa-soap:before {
  content: "\e06e"
}

.fa-heart-music-camera-bolt:before,
.fa-icons:before {
  content: "\f86d"
}

.fa-microphone-alt-slash:before,
.fa-microphone-lines-slash:before {
  content: "\f539"
}

.fa-bridge-circle-check:before {
  content: "\e4c9"
}

.fa-pump-medical:before {
  content: "\e06a"
}

.fa-fingerprint:before {
  content: "\f577"
}

.fa-hand-point-right:before {
  content: "\f0a4"
}

.fa-magnifying-glass-location:before,
.fa-search-location:before {
  content: "\f689"
}

.fa-forward-step:before,
.fa-step-forward:before {
  content: "\f051"
}

.fa-face-smile-beam:before,
.fa-smile-beam:before {
  content: "\f5b8"
}

.fa-flag-checkered:before {
  content: "\f11e"
}

.fa-football-ball:before,
.fa-football:before {
  content: "\f44e"
}

.fa-school-circle-exclamation:before {
  content: "\e56c"
}

.fa-crop:before {
  content: "\f125"
}

.fa-angle-double-down:before,
.fa-angles-down:before {
  content: "\f103"
}

.fa-users-rectangle:before {
  content: "\e594"
}

.fa-people-roof:before {
  content: "\e537"
}

.fa-people-line:before {
  content: "\e534"
}

.fa-beer-mug-empty:before,
.fa-beer:before {
  content: "\f0fc"
}

.fa-diagram-predecessor:before {
  content: "\e477"
}

.fa-arrow-up-long:before,
.fa-long-arrow-up:before {
  content: "\f176"
}

.fa-burn:before,
.fa-fire-flame-simple:before {
  content: "\f46a"
}

.fa-male:before,
.fa-person:before {
  content: "\f183"
}

.fa-laptop:before {
  content: "\f109"
}

.fa-file-csv:before {
  content: "\f6dd"
}

.fa-menorah:before {
  content: "\f676"
}

.fa-truck-plane:before {
  content: "\e58f"
}

.fa-record-vinyl:before {
  content: "\f8d9"
}

.fa-face-grin-stars:before,
.fa-grin-stars:before {
  content: "\f587"
}

.fa-bong:before {
  content: "\f55c"
}

.fa-pastafarianism:before,
.fa-spaghetti-monster-flying:before {
  content: "\f67b"
}

.fa-arrow-down-up-across-line:before {
  content: "\e4af"
}

.fa-spoon:before,
.fa-utensil-spoon:before {
  content: "\f2e5"
}

.fa-jar-wheat:before {
  content: "\e517"
}

.fa-envelopes-bulk:before,
.fa-mail-bulk:before {
  content: "\f674"
}

.fa-file-circle-exclamation:before {
  content: "\e4eb"
}

.fa-circle-h:before,
.fa-hospital-symbol:before {
  content: "\f47e"
}

.fa-pager:before {
  content: "\f815"
}

.fa-address-book:before,
.fa-contact-book:before {
  content: "\f2b9"
}

.fa-strikethrough:before {
  content: "\f0cc"
}

.fa-k:before {
  content: "\4b"
}

.fa-landmark-flag:before {
  content: "\e51c"
}

.fa-pencil-alt:before,
.fa-pencil:before {
  content: "\f303"
}

.fa-backward:before {
  content: "\f04a"
}

.fa-caret-right:before {
  content: "\f0da"
}

.fa-comments:before {
  content: "\f086"
}

.fa-file-clipboard:before,
.fa-paste:before {
  content: "\f0ea"
}

.fa-code-pull-request:before {
  content: "\e13c"
}

.fa-clipboard-list:before {
  content: "\f46d"
}

.fa-truck-loading:before,
.fa-truck-ramp-box:before {
  content: "\f4de"
}

.fa-user-check:before {
  content: "\f4fc"
}

.fa-vial-virus:before {
  content: "\e597"
}

.fa-sheet-plastic:before {
  content: "\e571"
}

.fa-blog:before {
  content: "\f781"
}

.fa-user-ninja:before {
  content: "\f504"
}

.fa-person-arrow-up-from-line:before {
  content: "\e539"
}

.fa-scroll-torah:before,
.fa-torah:before {
  content: "\f6a0"
}

.fa-broom-ball:before,
.fa-quidditch-broom-ball:before,
.fa-quidditch:before {
  content: "\f458"
}

.fa-toggle-off:before {
  content: "\f204"
}

.fa-archive:before,
.fa-box-archive:before {
  content: "\f187"
}

.fa-person-drowning:before {
  content: "\e545"
}

.fa-arrow-down-9-1:before,
.fa-sort-numeric-desc:before,
.fa-sort-numeric-down-alt:before {
  content: "\f886"
}

.fa-face-grin-tongue-squint:before,
.fa-grin-tongue-squint:before {
  content: "\f58a"
}

.fa-spray-can:before {
  content: "\f5bd"
}

.fa-truck-monster:before {
  content: "\f63b"
}

.fa-w:before {
  content: "\57"
}

.fa-earth-africa:before,
.fa-globe-africa:before {
  content: "\f57c"
}

.fa-rainbow:before {
  content: "\f75b"
}

.fa-circle-notch:before {
  content: "\f1ce"
}

.fa-tablet-alt:before,
.fa-tablet-screen-button:before {
  content: "\f3fa"
}

.fa-paw:before {
  content: "\f1b0"
}

.fa-cloud:before {
  content: "\f0c2"
}

.fa-trowel-bricks:before {
  content: "\e58a"
}

.fa-face-flushed:before,
.fa-flushed:before {
  content: "\f579"
}

.fa-hospital-user:before {
  content: "\f80d"
}

.fa-tent-arrow-left-right:before {
  content: "\e57f"
}

.fa-gavel:before,
.fa-legal:before {
  content: "\f0e3"
}

.fa-binoculars:before {
  content: "\f1e5"
}

.fa-microphone-slash:before {
  content: "\f131"
}

.fa-box-tissue:before {
  content: "\e05b"
}

.fa-motorcycle:before {
  content: "\f21c"
}

.fa-bell-concierge:before,
.fa-concierge-bell:before {
  content: "\f562"
}

.fa-pen-ruler:before,
.fa-pencil-ruler:before {
  content: "\f5ae"
}

.fa-people-arrows-left-right:before,
.fa-people-arrows:before {
  content: "\e068"
}

.fa-mars-and-venus-burst:before {
  content: "\e523"
}

.fa-caret-square-right:before,
.fa-square-caret-right:before {
  content: "\f152"
}

.fa-cut:before,
.fa-scissors:before {
  content: "\f0c4"
}

.fa-sun-plant-wilt:before {
  content: "\e57a"
}

.fa-toilets-portable:before {
  content: "\e584"
}

.fa-hockey-puck:before {
  content: "\f453"
}

.fa-table:before {
  content: "\f0ce"
}

.fa-magnifying-glass-arrow-right:before {
  content: "\e521"
}

.fa-digital-tachograph:before,
.fa-tachograph-digital:before {
  content: "\f566"
}

.fa-users-slash:before {
  content: "\e073"
}

.fa-clover:before {
  content: "\e139"
}

.fa-mail-reply:before,
.fa-reply:before {
  content: "\f3e5"
}

.fa-star-and-crescent:before {
  content: "\f699"
}

.fa-house-fire:before {
  content: "\e50c"
}

.fa-minus-square:before,
.fa-square-minus:before {
  content: "\f146"
}

.fa-helicopter:before {
  content: "\f533"
}

.fa-compass:before {
  content: "\f14e"
}

.fa-caret-square-down:before,
.fa-square-caret-down:before {
  content: "\f150"
}

.fa-file-circle-question:before {
  content: "\e4ef"
}

.fa-laptop-code:before {
  content: "\f5fc"
}

.fa-swatchbook:before {
  content: "\f5c3"
}

.fa-prescription-bottle:before {
  content: "\f485"
}

.fa-bars:before,
.fa-navicon:before {
  content: "\f0c9"
}

.fa-people-group:before {
  content: "\e533"
}

.fa-hourglass-3:before,
.fa-hourglass-end:before {
  content: "\f253"
}

.fa-heart-broken:before,
.fa-heart-crack:before {
  content: "\f7a9"
}

.fa-external-link-square-alt:before,
.fa-square-up-right:before {
  content: "\f360"
}

.fa-face-kiss-beam:before,
.fa-kiss-beam:before {
  content: "\f597"
}

.fa-film:before {
  content: "\f008"
}

.fa-ruler-horizontal:before {
  content: "\f547"
}

.fa-people-robbery:before {
  content: "\e536"
}

.fa-lightbulb:before {
  content: "\f0eb"
}

.fa-caret-left:before {
  content: "\f0d9"
}

.fa-circle-exclamation:before,
.fa-exclamation-circle:before {
  content: "\f06a"
}

.fa-school-circle-xmark:before {
  content: "\e56d"
}

.fa-arrow-right-from-bracket:before,
.fa-sign-out:before {
  content: "\f08b"
}

.fa-chevron-circle-down:before,
.fa-circle-chevron-down:before {
  content: "\f13a"
}

.fa-unlock-alt:before,
.fa-unlock-keyhole:before {
  content: "\f13e"
}

.fa-cloud-showers-heavy:before {
  content: "\f740"
}

.fa-headphones-alt:before,
.fa-headphones-simple:before {
  content: "\f58f"
}

.fa-sitemap:before {
  content: "\f0e8"
}

.fa-circle-dollar-to-slot:before,
.fa-donate:before {
  content: "\f4b9"
}

.fa-memory:before {
  content: "\f538"
}

.fa-road-spikes:before {
  content: "\e568"
}

.fa-fire-burner:before {
  content: "\e4f1"
}

.fa-flag:before {
  content: "\f024"
}

.fa-hanukiah:before {
  content: "\f6e6"
}

.fa-feather:before {
  content: "\f52d"
}

.fa-volume-down:before,
.fa-volume-low:before {
  content: "\f027"
}

.fa-comment-slash:before {
  content: "\f4b3"
}

.fa-cloud-sun-rain:before {
  content: "\f743"
}

.fa-compress:before {
  content: "\f066"
}

.fa-wheat-alt:before,
.fa-wheat-awn:before {
  content: "\e2cd"
}

.fa-ankh:before {
  content: "\f644"
}

.fa-hands-holding-child:before {
  content: "\e4fa"
}

.fa-asterisk:before {
  content: "\2a"
}

.fa-check-square:before,
.fa-square-check:before {
  content: "\f14a"
}

.fa-peseta-sign:before {
  content: "\e221"
}

.fa-header:before,
.fa-heading:before {
  content: "\f1dc"
}

.fa-ghost:before {
  content: "\f6e2"
}

.fa-list-squares:before,
.fa-list:before {
  content: "\f03a"
}

.fa-phone-square-alt:before,
.fa-square-phone-flip:before {
  content: "\f87b"
}

.fa-cart-plus:before {
  content: "\f217"
}

.fa-gamepad:before {
  content: "\f11b"
}

.fa-circle-dot:before,
.fa-dot-circle:before {
  content: "\f192"
}

.fa-dizzy:before,
.fa-face-dizzy:before {
  content: "\f567"
}

.fa-egg:before {
  content: "\f7fb"
}

.fa-house-medical-circle-xmark:before {
  content: "\e513"
}

.fa-campground:before {
  content: "\f6bb"
}

.fa-folder-plus:before {
  content: "\f65e"
}

.fa-futbol-ball:before,
.fa-futbol:before,
.fa-soccer-ball:before {
  content: "\f1e3"
}

.fa-paint-brush:before,
.fa-paintbrush:before {
  content: "\f1fc"
}

.fa-lock:before {
  content: "\f023"
}

.fa-gas-pump:before {
  content: "\f52f"
}

.fa-hot-tub-person:before,
.fa-hot-tub:before {
  content: "\f593"
}

.fa-map-location:before,
.fa-map-marked:before {
  content: "\f59f"
}

.fa-house-flood-water:before {
  content: "\e50e"
}

.fa-tree:before {
  content: "\f1bb"
}

.fa-bridge-lock:before {
  content: "\e4cc"
}

.fa-sack-dollar:before {
  content: "\f81d"
}

.fa-edit:before,
.fa-pen-to-square:before {
  content: "\f044"
}

.fa-car-side:before {
  content: "\f5e4"
}

.fa-share-alt:before,
.fa-share-nodes:before {
  content: "\f1e0"
}

.fa-heart-circle-minus:before {
  content: "\e4ff"
}

.fa-hourglass-2:before,
.fa-hourglass-half:before {
  content: "\f252"
}

.fa-microscope:before {
  content: "\f610"
}

.fa-sink:before {
  content: "\e06d"
}

.fa-bag-shopping:before,
.fa-shopping-bag:before {
  content: "\f290"
}

.fa-arrow-down-z-a:before,
.fa-sort-alpha-desc:before,
.fa-sort-alpha-down-alt:before {
  content: "\f881"
}

.fa-mitten:before {
  content: "\f7b5"
}

.fa-person-rays:before {
  content: "\e54d"
}

.fa-users:before {
  content: "\f0c0"
}

.fa-eye-slash:before {
  content: "\f070"
}

.fa-flask-vial:before {
  content: "\e4f3"
}

.fa-hand-paper:before,
.fa-hand:before {
  content: "\f256"
}

.fa-om:before {
  content: "\f679"
}

.fa-worm:before {
  content: "\e599"
}

.fa-house-circle-xmark:before {
  content: "\e50b"
}

.fa-plug:before {
  content: "\f1e6"
}

.fa-chevron-up:before {
  content: "\f077"
}

.fa-hand-spock:before {
  content: "\f259"
}

.fa-stopwatch:before {
  content: "\f2f2"
}

.fa-face-kiss:before,
.fa-kiss:before {
  content: "\f596"
}

.fa-bridge-circle-xmark:before {
  content: "\e4cb"
}

.fa-face-grin-tongue:before,
.fa-grin-tongue:before {
  content: "\f589"
}

.fa-chess-bishop:before {
  content: "\f43a"
}

.fa-face-grin-wink:before,
.fa-grin-wink:before {
  content: "\f58c"
}

.fa-deaf:before,
.fa-deafness:before,
.fa-ear-deaf:before,
.fa-hard-of-hearing:before {
  content: "\f2a4"
}

.fa-road-circle-check:before {
  content: "\e564"
}

.fa-dice-five:before {
  content: "\f523"
}

.fa-rss-square:before,
.fa-square-rss:before {
  content: "\f143"
}

.fa-land-mine-on:before {
  content: "\e51b"
}

.fa-i-cursor:before {
  content: "\f246"
}

.fa-stamp:before {
  content: "\f5bf"
}

.fa-stairs:before {
  content: "\e289"
}

.fa-i:before {
  content: "\49"
}

.fa-hryvnia-sign:before,
.fa-hryvnia:before {
  content: "\f6f2"
}

.fa-pills:before {
  content: "\f484"
}

.fa-face-grin-wide:before,
.fa-grin-alt:before {
  content: "\f581"
}

.fa-tooth:before {
  content: "\f5c9"
}

.fa-v:before {
  content: "\56"
}

.fa-bicycle:before {
  content: "\f206"
}

.fa-rod-asclepius:before,
.fa-rod-snake:before,
.fa-staff-aesculapius:before,
.fa-staff-snake:before {
  content: "\e579"
}

.fa-head-side-cough-slash:before {
  content: "\e062"
}

.fa-ambulance:before,
.fa-truck-medical:before {
  content: "\f0f9"
}

.fa-wheat-awn-circle-exclamation:before {
  content: "\e598"
}

.fa-snowman:before {
  content: "\f7d0"
}

.fa-mortar-pestle:before {
  content: "\f5a7"
}

.fa-road-barrier:before {
  content: "\e562"
}

.fa-school:before {
  content: "\f549"
}

.fa-igloo:before {
  content: "\f7ae"
}

.fa-joint:before {
  content: "\f595"
}

.fa-angle-right:before {
  content: "\f105"
}

.fa-horse:before {
  content: "\f6f0"
}

.fa-q:before {
  content: "\51"
}

.fa-g:before {
  content: "\47"
}

.fa-notes-medical:before {
  content: "\f481"
}

.fa-temperature-2:before,
.fa-temperature-half:before,
.fa-thermometer-2:before,
.fa-thermometer-half:before {
  content: "\f2c9"
}

.fa-dong-sign:before {
  content: "\e169"
}

.fa-capsules:before {
  content: "\f46b"
}

.fa-poo-bolt:before,
.fa-poo-storm:before {
  content: "\f75a"
}

.fa-face-frown-open:before,
.fa-frown-open:before {
  content: "\f57a"
}

.fa-hand-point-up:before {
  content: "\f0a6"
}

.fa-money-bill:before {
  content: "\f0d6"
}

.fa-bookmark:before {
  content: "\f02e"
}

.fa-align-justify:before {
  content: "\f039"
}

.fa-umbrella-beach:before {
  content: "\f5ca"
}

.fa-helmet-un:before {
  content: "\e503"
}

.fa-bullseye:before {
  content: "\f140"
}

.fa-bacon:before {
  content: "\f7e5"
}

.fa-hand-point-down:before {
  content: "\f0a7"
}

.fa-arrow-up-from-bracket:before {
  content: "\e09a"
}

.fa-folder-blank:before,
.fa-folder:before {
  content: "\f07b"
}

.fa-file-medical-alt:before,
.fa-file-waveform:before {
  content: "\f478"
}

.fa-radiation:before {
  content: "\f7b9"
}

.fa-chart-simple:before {
  content: "\e473"
}

.fa-mars-stroke:before {
  content: "\f229"
}

.fa-vial:before {
  content: "\f492"
}

.fa-dashboard:before,
.fa-gauge-med:before,
.fa-gauge:before,
.fa-tachometer-alt-average:before {
  content: "\f624"
}

.fa-magic-wand-sparkles:before,
.fa-wand-magic-sparkles:before {
  content: "\e2ca"
}

.fa-e:before {
  content: "\45"
}

.fa-pen-alt:before,
.fa-pen-clip:before {
  content: "\f305"
}

.fa-bridge-circle-exclamation:before {
  content: "\e4ca"
}

.fa-user:before {
  content: "\f007"
}

.fa-school-circle-check:before {
  content: "\e56b"
}

.fa-dumpster:before {
  content: "\f793"
}

.fa-shuttle-van:before,
.fa-van-shuttle:before {
  content: "\f5b6"
}

.fa-building-user:before {
  content: "\e4da"
}

.fa-caret-square-left:before,
.fa-square-caret-left:before {
  content: "\f191"
}

.fa-highlighter:before {
  content: "\f591"
}

.fa-key:before {
  content: "\f084"
}

.fa-bullhorn:before {
  content: "\f0a1"
}

.fa-globe:before {
  content: "\f0ac"
}

.fa-synagogue:before {
  content: "\f69b"
}

.fa-person-half-dress:before {
  content: "\e548"
}

.fa-road-bridge:before {
  content: "\e563"
}

.fa-location-arrow:before {
  content: "\f124"
}

.fa-c:before {
  content: "\43"
}

.fa-tablet-button:before {
  content: "\f10a"
}

.fa-building-lock:before {
  content: "\e4d6"
}

.fa-pizza-slice:before {
  content: "\f818"
}

.fa-money-bill-wave:before {
  content: "\f53a"
}

.fa-area-chart:before,
.fa-chart-area:before {
  content: "\f1fe"
}

.fa-house-flag:before {
  content: "\e50d"
}

.fa-person-circle-minus:before {
  content: "\e540"
}

.fa-ban:before,
.fa-cancel:before {
  content: "\f05e"
}

.fa-camera-rotate:before {
  content: "\e0d8"
}

.fa-air-freshener:before,
.fa-spray-can-sparkles:before {
  content: "\f5d0"
}

.fa-star:before {
  content: "\f005"
}

.fa-repeat:before {
  content: "\f363"
}

.fa-cross:before {
  content: "\f654"
}

.fa-box:before {
  content: "\f466"
}

.fa-venus-mars:before {
  content: "\f228"
}

.fa-arrow-pointer:before,
.fa-mouse-pointer:before {
  content: "\f245"
}

.fa-expand-arrows-alt:before,
.fa-maximize:before {
  content: "\f31e"
}

.fa-charging-station:before {
  content: "\f5e7"
}

.fa-shapes:before,
.fa-triangle-circle-square:before {
  content: "\f61f"
}

.fa-random:before,
.fa-shuffle:before {
  content: "\f074"
}

.fa-person-running:before,
.fa-running:before {
  content: "\f70c"
}

.fa-mobile-retro:before {
  content: "\e527"
}

.fa-grip-lines-vertical:before {
  content: "\f7a5"
}

.fa-spider:before {
  content: "\f717"
}

.fa-hands-bound:before {
  content: "\e4f9"
}

.fa-file-invoice-dollar:before {
  content: "\f571"
}

.fa-plane-circle-exclamation:before {
  content: "\e556"
}

.fa-x-ray:before {
  content: "\f497"
}

.fa-spell-check:before {
  content: "\f891"
}

.fa-slash:before {
  content: "\f715"
}

.fa-computer-mouse:before,
.fa-mouse:before {
  content: "\f8cc"
}

.fa-arrow-right-to-bracket:before,
.fa-sign-in:before {
  content: "\f090"
}

.fa-shop-slash:before,
.fa-store-alt-slash:before {
  content: "\e070"
}

.fa-server:before {
  content: "\f233"
}

.fa-virus-covid-slash:before {
  content: "\e4a9"
}

.fa-shop-lock:before {
  content: "\e4a5"
}

.fa-hourglass-1:before,
.fa-hourglass-start:before {
  content: "\f251"
}

.fa-blender-phone:before {
  content: "\f6b6"
}

.fa-building-wheat:before {
  content: "\e4db"
}

.fa-person-breastfeeding:before {
  content: "\e53a"
}

.fa-right-to-bracket:before,
.fa-sign-in-alt:before {
  content: "\f2f6"
}

.fa-venus:before {
  content: "\f221"
}

.fa-passport:before {
  content: "\f5ab"
}

.fa-heart-pulse:before,
.fa-heartbeat:before {
  content: "\f21e"
}

.fa-people-carry-box:before,
.fa-people-carry:before {
  content: "\f4ce"
}

.fa-temperature-high:before {
  content: "\f769"
}

.fa-microchip:before {
  content: "\f2db"
}

.fa-crown:before {
  content: "\f521"
}

.fa-weight-hanging:before {
  content: "\f5cd"
}

.fa-xmarks-lines:before {
  content: "\e59a"
}

.fa-file-prescription:before {
  content: "\f572"
}

.fa-weight-scale:before,
.fa-weight:before {
  content: "\f496"
}

.fa-user-friends:before,
.fa-user-group:before {
  content: "\f500"
}

.fa-arrow-up-a-z:before,
.fa-sort-alpha-up:before {
  content: "\f15e"
}

.fa-chess-knight:before {
  content: "\f441"
}

.fa-face-laugh-squint:before,
.fa-laugh-squint:before {
  content: "\f59b"
}

.fa-wheelchair:before {
  content: "\f193"
}

.fa-arrow-circle-up:before,
.fa-circle-arrow-up:before {
  content: "\f0aa"
}

.fa-toggle-on:before {
  content: "\f205"
}

.fa-person-walking:before,
.fa-walking:before {
  content: "\f554"
}

.fa-l:before {
  content: "\4c"
}

.fa-fire:before {
  content: "\f06d"
}

.fa-bed-pulse:before,
.fa-procedures:before {
  content: "\f487"
}

.fa-shuttle-space:before,
.fa-space-shuttle:before {
  content: "\f197"
}

.fa-face-laugh:before,
.fa-laugh:before {
  content: "\f599"
}

.fa-folder-open:before {
  content: "\f07c"
}

.fa-heart-circle-plus:before {
  content: "\e500"
}

.fa-code-fork:before {
  content: "\e13b"
}

.fa-city:before {
  content: "\f64f"
}

.fa-microphone-alt:before,
.fa-microphone-lines:before {
  content: "\f3c9"
}

.fa-pepper-hot:before {
  content: "\f816"
}

.fa-unlock:before {
  content: "\f09c"
}

.fa-colon-sign:before {
  content: "\e140"
}

.fa-headset:before {
  content: "\f590"
}

.fa-store-slash:before {
  content: "\e071"
}

.fa-road-circle-xmark:before {
  content: "\e566"
}

.fa-user-minus:before {
  content: "\f503"
}

.fa-mars-stroke-up:before,
.fa-mars-stroke-v:before {
  content: "\f22a"
}

.fa-champagne-glasses:before,
.fa-glass-cheers:before {
  content: "\f79f"
}

.fa-clipboard:before {
  content: "\f328"
}

.fa-house-circle-exclamation:before {
  content: "\e50a"
}

.fa-file-arrow-up:before,
.fa-file-upload:before {
  content: "\f574"
}

.fa-wifi-3:before,
.fa-wifi-strong:before,
.fa-wifi:before {
  content: "\f1eb"
}

.fa-bath:before,
.fa-bathtub:before {
  content: "\f2cd"
}

.fa-underline:before {
  content: "\f0cd"
}

.fa-user-edit:before,
.fa-user-pen:before {
  content: "\f4ff"
}

.fa-signature:before {
  content: "\f5b7"
}

.fa-stroopwafel:before {
  content: "\f551"
}

.fa-bold:before {
  content: "\f032"
}

.fa-anchor-lock:before {
  content: "\e4ad"
}

.fa-building-ngo:before {
  content: "\e4d7"
}

.fa-manat-sign:before {
  content: "\e1d5"
}

.fa-not-equal:before {
  content: "\f53e"
}

.fa-border-style:before,
.fa-border-top-left:before {
  content: "\f853"
}

.fa-map-location-dot:before,
.fa-map-marked-alt:before {
  content: "\f5a0"
}

.fa-jedi:before {
  content: "\f669"
}

.fa-poll:before,
.fa-square-poll-vertical:before {
  content: "\f681"
}

.fa-mug-hot:before {
  content: "\f7b6"
}

.fa-battery-car:before,
.fa-car-battery:before {
  content: "\f5df"
}

.fa-gift:before {
  content: "\f06b"
}

.fa-dice-two:before {
  content: "\f528"
}

.fa-chess-queen:before {
  content: "\f445"
}

.fa-glasses:before {
  content: "\f530"
}

.fa-chess-board:before {
  content: "\f43c"
}

.fa-building-circle-check:before {
  content: "\e4d2"
}

.fa-person-chalkboard:before {
  content: "\e53d"
}

.fa-mars-stroke-h:before,
.fa-mars-stroke-right:before {
  content: "\f22b"
}

.fa-hand-back-fist:before,
.fa-hand-rock:before {
  content: "\f255"
}

.fa-caret-square-up:before,
.fa-square-caret-up:before {
  content: "\f151"
}

.fa-cloud-showers-water:before {
  content: "\e4e4"
}

.fa-bar-chart:before,
.fa-chart-bar:before {
  content: "\f080"
}

.fa-hands-bubbles:before,
.fa-hands-wash:before {
  content: "\e05e"
}

.fa-less-than-equal:before {
  content: "\f537"
}

.fa-train:before {
  content: "\f238"
}

.fa-eye-low-vision:before,
.fa-low-vision:before {
  content: "\f2a8"
}

.fa-crow:before {
  content: "\f520"
}

.fa-sailboat:before {
  content: "\e445"
}

.fa-window-restore:before {
  content: "\f2d2"
}

.fa-plus-square:before,
.fa-square-plus:before {
  content: "\f0fe"
}

.fa-torii-gate:before {
  content: "\f6a1"
}

.fa-frog:before {
  content: "\f52e"
}

.fa-bucket:before {
  content: "\e4cf"
}

.fa-image:before {
  content: "\f03e"
}

.fa-microphone:before {
  content: "\f130"
}

.fa-cow:before {
  content: "\f6c8"
}

.fa-caret-up:before {
  content: "\f0d8"
}

.fa-screwdriver:before {
  content: "\f54a"
}

.fa-folder-closed:before {
  content: "\e185"
}

.fa-house-tsunami:before {
  content: "\e515"
}

.fa-square-nfi:before {
  content: "\e576"
}

.fa-arrow-up-from-ground-water:before {
  content: "\e4b5"
}

.fa-glass-martini-alt:before,
.fa-martini-glass:before {
  content: "\f57b"
}

.fa-rotate-back:before,
.fa-rotate-backward:before,
.fa-rotate-left:before,
.fa-undo-alt:before {
  content: "\f2ea"
}

.fa-columns:before,
.fa-table-columns:before {
  content: "\f0db"
}

.fa-lemon:before {
  content: "\f094"
}

.fa-head-side-mask:before {
  content: "\e063"
}

.fa-handshake:before {
  content: "\f2b5"
}

.fa-gem:before {
  content: "\f3a5"
}

.fa-dolly-box:before,
.fa-dolly:before {
  content: "\f472"
}

.fa-smoking:before {
  content: "\f48d"
}

.fa-compress-arrows-alt:before,
.fa-minimize:before {
  content: "\f78c"
}

.fa-monument:before {
  content: "\f5a6"
}

.fa-snowplow:before {
  content: "\f7d2"
}

.fa-angle-double-right:before,
.fa-angles-right:before {
  content: "\f101"
}

.fa-cannabis:before {
  content: "\f55f"
}

.fa-circle-play:before,
.fa-play-circle:before {
  content: "\f144"
}

.fa-tablets:before {
  content: "\f490"
}

.fa-ethernet:before {
  content: "\f796"
}

.fa-eur:before,
.fa-euro-sign:before,
.fa-euro:before {
  content: "\f153"
}

.fa-chair:before {
  content: "\f6c0"
}

.fa-check-circle:before,
.fa-circle-check:before {
  content: "\f058"
}

.fa-circle-stop:before,
.fa-stop-circle:before {
  content: "\f28d"
}

.fa-compass-drafting:before,
.fa-drafting-compass:before {
  content: "\f568"
}

.fa-plate-wheat:before {
  content: "\e55a"
}

.fa-icicles:before {
  content: "\f7ad"
}

.fa-person-shelter:before {
  content: "\e54f"
}

.fa-neuter:before {
  content: "\f22c"
}

.fa-id-badge:before {
  content: "\f2c1"
}

.fa-marker:before {
  content: "\f5a1"
}

.fa-face-laugh-beam:before,
.fa-laugh-beam:before {
  content: "\f59a"
}

.fa-helicopter-symbol:before {
  content: "\e502"
}

.fa-universal-access:before {
  content: "\f29a"
}

.fa-chevron-circle-up:before,
.fa-circle-chevron-up:before {
  content: "\f139"
}

.fa-lari-sign:before {
  content: "\e1c8"
}

.fa-volcano:before {
  content: "\f770"
}

.fa-person-walking-dashed-line-arrow-right:before {
  content: "\e553"
}

.fa-gbp:before,
.fa-pound-sign:before,
.fa-sterling-sign:before {
  content: "\f154"
}

.fa-viruses:before {
  content: "\e076"
}

.fa-square-person-confined:before {
  content: "\e577"
}

.fa-user-tie:before {
  content: "\f508"
}

.fa-arrow-down-long:before,
.fa-long-arrow-down:before {
  content: "\f175"
}

.fa-tent-arrow-down-to-line:before {
  content: "\e57e"
}

.fa-certificate:before {
  content: "\f0a3"
}

.fa-mail-reply-all:before,
.fa-reply-all:before {
  content: "\f122"
}

.fa-suitcase:before {
  content: "\f0f2"
}

.fa-person-skating:before,
.fa-skating:before {
  content: "\f7c5"
}

.fa-filter-circle-dollar:before,
.fa-funnel-dollar:before {
  content: "\f662"
}

.fa-camera-retro:before {
  content: "\f083"
}

.fa-arrow-circle-down:before,
.fa-circle-arrow-down:before {
  content: "\f0ab"
}

.fa-arrow-right-to-file:before,
.fa-file-import:before {
  content: "\f56f"
}

.fa-external-link-square:before,
.fa-square-arrow-up-right:before {
  content: "\f14c"
}

.fa-box-open:before {
  content: "\f49e"
}

.fa-scroll:before {
  content: "\f70e"
}

.fa-spa:before {
  content: "\f5bb"
}

.fa-location-pin-lock:before {
  content: "\e51f"
}

.fa-pause:before {
  content: "\f04c"
}

.fa-hill-avalanche:before {
  content: "\e507"
}

.fa-temperature-0:before,
.fa-temperature-empty:before,
.fa-thermometer-0:before,
.fa-thermometer-empty:before {
  content: "\f2cb"
}

.fa-bomb:before {
  content: "\f1e2"
}

.fa-registered:before {
  content: "\f25d"
}

.fa-address-card:before,
.fa-contact-card:before,
.fa-vcard:before {
  content: "\f2bb"
}

.fa-balance-scale-right:before,
.fa-scale-unbalanced-flip:before {
  content: "\f516"
}

.fa-subscript:before {
  content: "\f12c"
}

.fa-diamond-turn-right:before,
.fa-directions:before {
  content: "\f5eb"
}

.fa-burst:before {
  content: "\e4dc"
}

.fa-house-laptop:before,
.fa-laptop-house:before {
  content: "\e066"
}

.fa-face-tired:before,
.fa-tired:before {
  content: "\f5c8"
}

.fa-money-bills:before {
  content: "\e1f3"
}

.fa-smog:before {
  content: "\f75f"
}

.fa-crutch:before {
  content: "\f7f7"
}

.fa-cloud-arrow-up:before,
.fa-cloud-upload-alt:before,
.fa-cloud-upload:before {
  content: "\f0ee"
}

.fa-palette:before {
  content: "\f53f"
}

.fa-arrows-turn-right:before {
  content: "\e4c0"
}

.fa-vest:before {
  content: "\e085"
}

.fa-ferry:before {
  content: "\e4ea"
}

.fa-arrows-down-to-people:before {
  content: "\e4b9"
}

.fa-seedling:before,
.fa-sprout:before {
  content: "\f4d8"
}

.fa-arrows-alt-h:before,
.fa-left-right:before {
  content: "\f337"
}

.fa-boxes-packing:before {
  content: "\e4c7"
}

.fa-arrow-circle-left:before,
.fa-circle-arrow-left:before {
  content: "\f0a8"
}

.fa-group-arrows-rotate:before {
  content: "\e4f6"
}

.fa-bowl-food:before {
  content: "\e4c6"
}

.fa-candy-cane:before {
  content: "\f786"
}

.fa-arrow-down-wide-short:before,
.fa-sort-amount-asc:before,
.fa-sort-amount-down:before {
  content: "\f160"
}

.fa-cloud-bolt:before,
.fa-thunderstorm:before {
  content: "\f76c"
}

.fa-remove-format:before,
.fa-text-slash:before {
  content: "\f87d"
}

.fa-face-smile-wink:before,
.fa-smile-wink:before {
  content: "\f4da"
}

.fa-file-word:before {
  content: "\f1c2"
}

.fa-file-powerpoint:before {
  content: "\f1c4"
}

.fa-arrows-h:before,
.fa-arrows-left-right:before {
  content: "\f07e"
}

.fa-house-lock:before {
  content: "\e510"
}

.fa-cloud-arrow-down:before,
.fa-cloud-download-alt:before,
.fa-cloud-download:before {
  content: "\f0ed"
}

.fa-children:before {
  content: "\e4e1"
}

.fa-blackboard:before,
.fa-chalkboard:before {
  content: "\f51b"
}

.fa-user-alt-slash:before,
.fa-user-large-slash:before {
  content: "\f4fa"
}

.fa-envelope-open:before {
  content: "\f2b6"
}

.fa-handshake-alt-slash:before,
.fa-handshake-simple-slash:before {
  content: "\e05f"
}

.fa-mattress-pillow:before {
  content: "\e525"
}

.fa-guarani-sign:before {
  content: "\e19a"
}

.fa-arrows-rotate:before,
.fa-refresh:before,
.fa-sync:before {
  content: "\f021"
}

.fa-fire-extinguisher:before {
  content: "\f134"
}

.fa-cruzeiro-sign:before {
  content: "\e152"
}

.fa-greater-than-equal:before {
  content: "\f532"
}

.fa-shield-alt:before,
.fa-shield-halved:before {
  content: "\f3ed"
}

.fa-atlas:before,
.fa-book-atlas:before {
  content: "\f558"
}

.fa-virus:before {
  content: "\e074"
}

.fa-envelope-circle-check:before {
  content: "\e4e8"
}

.fa-layer-group:before {
  content: "\f5fd"
}

.fa-arrows-to-dot:before {
  content: "\e4be"
}

.fa-archway:before {
  content: "\f557"
}

.fa-heart-circle-check:before {
  content: "\e4fd"
}

.fa-house-chimney-crack:before,
.fa-house-damage:before {
  content: "\f6f1"
}

.fa-file-archive:before,
.fa-file-zipper:before {
  content: "\f1c6"
}

.fa-square:before {
  content: "\f0c8"
}

.fa-glass-martini:before,
.fa-martini-glass-empty:before {
  content: "\f000"
}

.fa-couch:before {
  content: "\f4b8"
}

.fa-cedi-sign:before {
  content: "\e0df"
}

.fa-italic:before {
  content: "\f033"
}

.fa-church:before {
  content: "\f51d"
}

.fa-comments-dollar:before {
  content: "\f653"
}

.fa-democrat:before {
  content: "\f747"
}

.fa-z:before {
  content: "\5a"
}

.fa-person-skiing:before,
.fa-skiing:before {
  content: "\f7c9"
}

.fa-road-lock:before {
  content: "\e567"
}

.fa-a:before {
  content: "\41"
}

.fa-temperature-arrow-down:before,
.fa-temperature-down:before {
  content: "\e03f"
}

.fa-feather-alt:before,
.fa-feather-pointed:before {
  content: "\f56b"
}

.fa-p:before {
  content: "\50"
}

.fa-snowflake:before {
  content: "\f2dc"
}

.fa-newspaper:before {
  content: "\f1ea"
}

.fa-ad:before,
.fa-rectangle-ad:before {
  content: "\f641"
}

.fa-arrow-circle-right:before,
.fa-circle-arrow-right:before {
  content: "\f0a9"
}

.fa-filter-circle-xmark:before {
  content: "\e17b"
}

.fa-locust:before {
  content: "\e520"
}

.fa-sort:before,
.fa-unsorted:before {
  content: "\f0dc"
}

.fa-list-1-2:before,
.fa-list-numeric:before,
.fa-list-ol:before {
  content: "\f0cb"
}

.fa-person-dress-burst:before {
  content: "\e544"
}

.fa-money-check-alt:before,
.fa-money-check-dollar:before {
  content: "\f53d"
}

.fa-vector-square:before {
  content: "\f5cb"
}

.fa-bread-slice:before {
  content: "\f7ec"
}

.fa-language:before {
  content: "\f1ab"
}

.fa-face-kiss-wink-heart:before,
.fa-kiss-wink-heart:before {
  content: "\f598"
}

.fa-filter:before {
  content: "\f0b0"
}

.fa-question:before {
  content: "\3f"
}

.fa-file-signature:before {
  content: "\f573"
}

.fa-arrows-alt:before,
.fa-up-down-left-right:before {
  content: "\f0b2"
}

.fa-house-chimney-user:before {
  content: "\e065"
}

.fa-hand-holding-heart:before {
  content: "\f4be"
}

.fa-puzzle-piece:before {
  content: "\f12e"
}

.fa-money-check:before {
  content: "\f53c"
}

.fa-star-half-alt:before,
.fa-star-half-stroke:before {
  content: "\f5c0"
}

.fa-code:before {
  content: "\f121"
}

.fa-glass-whiskey:before,
.fa-whiskey-glass:before {
  content: "\f7a0"
}

.fa-building-circle-exclamation:before {
  content: "\e4d3"
}

.fa-magnifying-glass-chart:before {
  content: "\e522"
}

.fa-arrow-up-right-from-square:before,
.fa-external-link:before {
  content: "\f08e"
}

.fa-cubes-stacked:before {
  content: "\e4e6"
}

.fa-krw:before,
.fa-won-sign:before,
.fa-won:before {
  content: "\f159"
}

.fa-virus-covid:before {
  content: "\e4a8"
}

.fa-austral-sign:before {
  content: "\e0a9"
}

.fa-f:before {
  content: "\46"
}

.fa-leaf:before {
  content: "\f06c"
}

.fa-road:before {
  content: "\f018"
}

.fa-cab:before,
.fa-taxi:before {
  content: "\f1ba"
}

.fa-person-circle-plus:before {
  content: "\e541"
}

.fa-chart-pie:before,
.fa-pie-chart:before {
  content: "\f200"
}

.fa-bolt-lightning:before {
  content: "\e0b7"
}

.fa-sack-xmark:before {
  content: "\e56a"
}

.fa-file-excel:before {
  content: "\f1c3"
}

.fa-file-contract:before {
  content: "\f56c"
}

.fa-fish-fins:before {
  content: "\e4f2"
}

.fa-building-flag:before {
  content: "\e4d5"
}

.fa-face-grin-beam:before,
.fa-grin-beam:before {
  content: "\f582"
}

.fa-object-ungroup:before {
  content: "\f248"
}

.fa-poop:before {
  content: "\f619"
}

.fa-location-pin:before,
.fa-map-marker:before {
  content: "\f041"
}

.fa-kaaba:before {
  content: "\f66b"
}

.fa-toilet-paper:before {
  content: "\f71e"
}

.fa-hard-hat:before,
.fa-hat-hard:before,
.fa-helmet-safety:before {
  content: "\f807"
}

.fa-eject:before {
  content: "\f052"
}

.fa-arrow-alt-circle-right:before,
.fa-circle-right:before {
  content: "\f35a"
}

.fa-plane-circle-check:before {
  content: "\e555"
}

.fa-face-rolling-eyes:before,
.fa-meh-rolling-eyes:before {
  content: "\f5a5"
}

.fa-object-group:before {
  content: "\f247"
}

.fa-chart-line:before,
.fa-line-chart:before {
  content: "\f201"
}

.fa-mask-ventilator:before {
  content: "\e524"
}

.fa-arrow-right:before {
  content: "\f061"
}

.fa-map-signs:before,
.fa-signs-post:before {
  content: "\f277"
}

.fa-cash-register:before {
  content: "\f788"
}

.fa-person-circle-question:before {
  content: "\e542"
}

.fa-h:before {
  content: "\48"
}

.fa-tarp:before {
  content: "\e57b"
}

.fa-screwdriver-wrench:before,
.fa-tools:before {
  content: "\f7d9"
}

.fa-arrows-to-eye:before {
  content: "\e4bf"
}

.fa-plug-circle-bolt:before {
  content: "\e55b"
}

.fa-heart:before {
  content: "\f004"
}

.fa-mars-and-venus:before {
  content: "\f224"
}

.fa-home-user:before,
.fa-house-user:before {
  content: "\e1b0"
}

.fa-dumpster-fire:before {
  content: "\f794"
}

.fa-house-crack:before {
  content: "\e3b1"
}

.fa-cocktail:before,
.fa-martini-glass-citrus:before {
  content: "\f561"
}

.fa-face-surprise:before,
.fa-surprise:before {
  content: "\f5c2"
}

.fa-bottle-water:before {
  content: "\e4c5"
}

.fa-circle-pause:before,
.fa-pause-circle:before {
  content: "\f28b"
}

.fa-toilet-paper-slash:before {
  content: "\e072"
}

.fa-apple-alt:before,
.fa-apple-whole:before {
  content: "\f5d1"
}

.fa-kitchen-set:before {
  content: "\e51a"
}

.fa-r:before {
  content: "\52"
}

.fa-temperature-1:before,
.fa-temperature-quarter:before,
.fa-thermometer-1:before,
.fa-thermometer-quarter:before {
  content: "\f2ca"
}

.fa-cube:before {
  content: "\f1b2"
}

.fa-bitcoin-sign:before {
  content: "\e0b4"
}

.fa-shield-dog:before {
  content: "\e573"
}

.fa-solar-panel:before {
  content: "\f5ba"
}

.fa-lock-open:before {
  content: "\f3c1"
}

.fa-elevator:before {
  content: "\e16d"
}

.fa-money-bill-transfer:before {
  content: "\e528"
}

.fa-money-bill-trend-up:before {
  content: "\e529"
}

.fa-house-flood-water-circle-arrow-right:before {
  content: "\e50f"
}

.fa-poll-h:before,
.fa-square-poll-horizontal:before {
  content: "\f682"
}

.fa-circle:before {
  content: "\f111"
}

.fa-backward-fast:before,
.fa-fast-backward:before {
  content: "\f049"
}

.fa-recycle:before {
  content: "\f1b8"
}

.fa-user-astronaut:before {
  content: "\f4fb"
}

.fa-plane-slash:before {
  content: "\e069"
}

.fa-trademark:before {
  content: "\f25c"
}

.fa-basketball-ball:before,
.fa-basketball:before {
  content: "\f434"
}

.fa-satellite-dish:before {
  content: "\f7c0"
}

.fa-arrow-alt-circle-up:before,
.fa-circle-up:before {
  content: "\f35b"
}

.fa-mobile-alt:before,
.fa-mobile-screen-button:before {
  content: "\f3cd"
}

.fa-volume-high:before,
.fa-volume-up:before {
  content: "\f028"
}

.fa-users-rays:before {
  content: "\e593"
}

.fa-wallet:before {
  content: "\f555"
}

.fa-clipboard-check:before {
  content: "\f46c"
}

.fa-file-audio:before {
  content: "\f1c7"
}

.fa-burger:before,
.fa-hamburger:before {
  content: "\f805"
}

.fa-wrench:before {
  content: "\f0ad"
}

.fa-bugs:before {
  content: "\e4d0"
}

.fa-rupee-sign:before,
.fa-rupee:before {
  content: "\f156"
}

.fa-file-image:before {
  content: "\f1c5"
}

.fa-circle-question:before,
.fa-question-circle:before {
  content: "\f059"
}

.fa-plane-departure:before {
  content: "\f5b0"
}

.fa-handshake-slash:before {
  content: "\e060"
}

.fa-book-bookmark:before {
  content: "\e0bb"
}

.fa-code-branch:before {
  content: "\f126"
}

.fa-hat-cowboy:before {
  content: "\f8c0"
}

.fa-bridge:before {
  content: "\e4c8"
}

.fa-phone-alt:before,
.fa-phone-flip:before {
  content: "\f879"
}

.fa-truck-front:before {
  content: "\e2b7"
}

.fa-cat:before {
  content: "\f6be"
}

.fa-anchor-circle-exclamation:before {
  content: "\e4ab"
}

.fa-truck-field:before {
  content: "\e58d"
}

.fa-route:before {
  content: "\f4d7"
}

.fa-clipboard-question:before {
  content: "\e4e3"
}

.fa-panorama:before {
  content: "\e209"
}

.fa-comment-medical:before {
  content: "\f7f5"
}

.fa-teeth-open:before {
  content: "\f62f"
}

.fa-file-circle-minus:before {
  content: "\e4ed"
}

.fa-tags:before {
  content: "\f02c"
}

.fa-wine-glass:before {
  content: "\f4e3"
}

.fa-fast-forward:before,
.fa-forward-fast:before {
  content: "\f050"
}

.fa-face-meh-blank:before,
.fa-meh-blank:before {
  content: "\f5a4"
}

.fa-parking:before,
.fa-square-parking:before {
  content: "\f540"
}

.fa-house-signal:before {
  content: "\e012"
}

.fa-bars-progress:before,
.fa-tasks-alt:before {
  content: "\f828"
}

.fa-faucet-drip:before {
  content: "\e006"
}

.fa-cart-flatbed:before,
.fa-dolly-flatbed:before {
  content: "\f474"
}

.fa-ban-smoking:before,
.fa-smoking-ban:before {
  content: "\f54d"
}

.fa-terminal:before {
  content: "\f120"
}

.fa-mobile-button:before {
  content: "\f10b"
}

.fa-house-medical-flag:before {
  content: "\e514"
}

.fa-basket-shopping:before,
.fa-shopping-basket:before {
  content: "\f291"
}

.fa-tape:before {
  content: "\f4db"
}

.fa-bus-alt:before,
.fa-bus-simple:before {
  content: "\f55e"
}

.fa-eye:before {
  content: "\f06e"
}

.fa-face-sad-cry:before,
.fa-sad-cry:before {
  content: "\f5b3"
}

.fa-audio-description:before {
  content: "\f29e"
}

.fa-person-military-to-person:before {
  content: "\e54c"
}

.fa-file-shield:before {
  content: "\e4f0"
}

.fa-user-slash:before {
  content: "\f506"
}

.fa-pen:before {
  content: "\f304"
}

.fa-tower-observation:before {
  content: "\e586"
}

.fa-file-code:before {
  content: "\f1c9"
}

.fa-signal-5:before,
.fa-signal-perfect:before,
.fa-signal:before {
  content: "\f012"
}

.fa-bus:before {
  content: "\f207"
}

.fa-heart-circle-xmark:before {
  content: "\e501"
}

.fa-home-lg:before,
.fa-house-chimney:before {
  content: "\e3af"
}

.fa-window-maximize:before {
  content: "\f2d0"
}

.fa-face-frown:before,
.fa-frown:before {
  content: "\f119"
}

.fa-prescription:before {
  content: "\f5b1"
}

.fa-shop:before,
.fa-store-alt:before {
  content: "\f54f"
}

.fa-floppy-disk:before,
.fa-save:before {
  content: "\f0c7"
}

.fa-vihara:before {
  content: "\f6a7"
}

.fa-balance-scale-left:before,
.fa-scale-unbalanced:before {
  content: "\f515"
}

.fa-sort-asc:before,
.fa-sort-up:before {
  content: "\f0de"
}

.fa-comment-dots:before,
.fa-commenting:before {
  content: "\f4ad"
}

.fa-plant-wilt:before {
  content: "\e5aa"
}

.fa-diamond:before {
  content: "\f219"
}

.fa-face-grin-squint:before,
.fa-grin-squint:before {
  content: "\f585"
}

.fa-hand-holding-dollar:before,
.fa-hand-holding-usd:before {
  content: "\f4c0"
}

.fa-bacterium:before {
  content: "\e05a"
}

.fa-hand-pointer:before {
  content: "\f25a"
}

.fa-drum-steelpan:before {
  content: "\f56a"
}

.fa-hand-scissors:before {
  content: "\f257"
}

.fa-hands-praying:before,
.fa-praying-hands:before {
  content: "\f684"
}

.fa-arrow-right-rotate:before,
.fa-arrow-rotate-forward:before,
.fa-arrow-rotate-right:before,
.fa-redo:before {
  content: "\f01e"
}

.fa-biohazard:before {
  content: "\f780"
}

.fa-location-crosshairs:before,
.fa-location:before {
  content: "\f601"
}

.fa-mars-double:before {
  content: "\f227"
}

.fa-child-dress:before {
  content: "\e59c"
}

.fa-users-between-lines:before {
  content: "\e591"
}

.fa-lungs-virus:before {
  content: "\e067"
}

.fa-face-grin-tears:before,
.fa-grin-tears:before {
  content: "\f588"
}

.fa-phone:before {
  content: "\f095"
}

.fa-calendar-times:before,
.fa-calendar-xmark:before {
  content: "\f273"
}

.fa-child-reaching:before {
  content: "\e59d"
}

.fa-head-side-virus:before {
  content: "\e064"
}

.fa-user-cog:before,
.fa-user-gear:before {
  content: "\f4fe"
}

.fa-arrow-up-1-9:before,
.fa-sort-numeric-up:before {
  content: "\f163"
}

.fa-door-closed:before {
  content: "\f52a"
}

.fa-shield-virus:before {
  content: "\e06c"
}

.fa-dice-six:before {
  content: "\f526"
}

.fa-mosquito-net:before {
  content: "\e52c"
}

.fa-bridge-water:before {
  content: "\e4ce"
}

.fa-person-booth:before {
  content: "\f756"
}

.fa-text-width:before {
  content: "\f035"
}

.fa-hat-wizard:before {
  content: "\f6e8"
}

.fa-pen-fancy:before {
  content: "\f5ac"
}

.fa-digging:before,
.fa-person-digging:before {
  content: "\f85e"
}

.fa-trash:before {
  content: "\f1f8"
}

.fa-gauge-simple-med:before,
.fa-gauge-simple:before,
.fa-tachometer-average:before {
  content: "\f629"
}

.fa-book-medical:before {
  content: "\f7e6"
}

.fa-poo:before {
  content: "\f2fe"
}

.fa-quote-right-alt:before,
.fa-quote-right:before {
  content: "\f10e"
}

.fa-shirt:before,
.fa-t-shirt:before,
.fa-tshirt:before {
  content: "\f553"
}

.fa-cubes:before {
  content: "\f1b3"
}

.fa-divide:before {
  content: "\f529"
}

.fa-tenge-sign:before,
.fa-tenge:before {
  content: "\f7d7"
}

.fa-headphones:before {
  content: "\f025"
}

.fa-hands-holding:before {
  content: "\f4c2"
}

.fa-hands-clapping:before {
  content: "\e1a8"
}

.fa-republican:before {
  content: "\f75e"
}

.fa-arrow-left:before {
  content: "\f060"
}

.fa-person-circle-xmark:before {
  content: "\e543"
}

.fa-ruler:before {
  content: "\f545"
}

.fa-align-left:before {
  content: "\f036"
}

.fa-dice-d6:before {
  content: "\f6d1"
}

.fa-restroom:before {
  content: "\f7bd"
}

.fa-j:before {
  content: "\4a"
}

.fa-users-viewfinder:before {
  content: "\e595"
}

.fa-file-video:before {
  content: "\f1c8"
}

.fa-external-link-alt:before,
.fa-up-right-from-square:before {
  content: "\f35d"
}

.fa-table-cells:before,
.fa-th:before {
  content: "\f00a"
}

.fa-file-pdf:before {
  content: "\f1c1"
}

.fa-bible:before,
.fa-book-bible:before {
  content: "\f647"
}

.fa-o:before {
  content: "\4f"
}

.fa-medkit:before,
.fa-suitcase-medical:before {
  content: "\f0fa"
}

.fa-user-secret:before {
  content: "\f21b"
}

.fa-otter:before {
  content: "\f700"
}

.fa-female:before,
.fa-person-dress:before {
  content: "\f182"
}

.fa-comment-dollar:before {
  content: "\f651"
}

.fa-briefcase-clock:before,
.fa-business-time:before {
  content: "\f64a"
}

.fa-table-cells-large:before,
.fa-th-large:before {
  content: "\f009"
}

.fa-book-tanakh:before,
.fa-tanakh:before {
  content: "\f827"
}

.fa-phone-volume:before,
.fa-volume-control-phone:before {
  content: "\f2a0"
}

.fa-hat-cowboy-side:before {
  content: "\f8c1"
}

.fa-clipboard-user:before {
  content: "\f7f3"
}

.fa-child:before {
  content: "\f1ae"
}

.fa-lira-sign:before {
  content: "\f195"
}

.fa-satellite:before {
  content: "\f7bf"
}

.fa-plane-lock:before {
  content: "\e558"
}

.fa-tag:before {
  content: "\f02b"
}

.fa-comment:before {
  content: "\f075"
}

.fa-birthday-cake:before,
.fa-cake-candles:before,
.fa-cake:before {
  content: "\f1fd"
}

.fa-envelope:before {
  content: "\f0e0"
}

.fa-angle-double-up:before,
.fa-angles-up:before {
  content: "\f102"
}

.fa-paperclip:before {
  content: "\f0c6"
}

.fa-arrow-right-to-city:before {
  content: "\e4b3"
}

.fa-ribbon:before {
  content: "\f4d6"
}

.fa-lungs:before {
  content: "\f604"
}

.fa-arrow-up-9-1:before,
.fa-sort-numeric-up-alt:before {
  content: "\f887"
}

.fa-litecoin-sign:before {
  content: "\e1d3"
}

.fa-border-none:before {
  content: "\f850"
}

.fa-circle-nodes:before {
  content: "\e4e2"
}

.fa-parachute-box:before {
  content: "\f4cd"
}

.fa-indent:before {
  content: "\f03c"
}

.fa-truck-field-un:before {
  content: "\e58e"
}

.fa-hourglass-empty:before,
.fa-hourglass:before {
  content: "\f254"
}

.fa-mountain:before {
  content: "\f6fc"
}

.fa-user-doctor:before,
.fa-user-md:before {
  content: "\f0f0"
}

.fa-circle-info:before,
.fa-info-circle:before {
  content: "\f05a"
}

.fa-cloud-meatball:before {
  content: "\f73b"
}

.fa-camera-alt:before,
.fa-camera:before {
  content: "\f030"
}

.fa-square-virus:before {
  content: "\e578"
}

.fa-meteor:before {
  content: "\f753"
}

.fa-car-on:before {
  content: "\e4dd"
}

.fa-sleigh:before {
  content: "\f7cc"
}

.fa-arrow-down-1-9:before,
.fa-sort-numeric-asc:before,
.fa-sort-numeric-down:before {
  content: "\f162"
}

.fa-hand-holding-droplet:before,
.fa-hand-holding-water:before {
  content: "\f4c1"
}

.fa-water:before {
  content: "\f773"
}

.fa-calendar-check:before {
  content: "\f274"
}

.fa-braille:before {
  content: "\f2a1"
}

.fa-prescription-bottle-alt:before,
.fa-prescription-bottle-medical:before {
  content: "\f486"
}

.fa-landmark:before {
  content: "\f66f"
}

.fa-truck:before {
  content: "\f0d1"
}

.fa-crosshairs:before {
  content: "\f05b"
}

.fa-person-cane:before {
  content: "\e53c"
}

.fa-tent:before {
  content: "\e57d"
}

.fa-vest-patches:before {
  content: "\e086"
}

.fa-check-double:before {
  content: "\f560"
}

.fa-arrow-down-a-z:before,
.fa-sort-alpha-asc:before,
.fa-sort-alpha-down:before {
  content: "\f15d"
}

.fa-money-bill-wheat:before {
  content: "\e52a"
}

.fa-cookie:before {
  content: "\f563"
}

.fa-arrow-left-rotate:before,
.fa-arrow-rotate-back:before,
.fa-arrow-rotate-backward:before,
.fa-arrow-rotate-left:before,
.fa-undo:before {
  content: "\f0e2"
}

.fa-hard-drive:before,
.fa-hdd:before {
  content: "\f0a0"
}

.fa-face-grin-squint-tears:before,
.fa-grin-squint-tears:before {
  content: "\f586"
}

.fa-dumbbell:before {
  content: "\f44b"
}

.fa-list-alt:before,
.fa-rectangle-list:before {
  content: "\f022"
}

.fa-tarp-droplet:before {
  content: "\e57c"
}

.fa-house-medical-circle-check:before {
  content: "\e511"
}

.fa-person-skiing-nordic:before,
.fa-skiing-nordic:before {
  content: "\f7ca"
}

.fa-calendar-plus:before {
  content: "\f271"
}

.fa-plane-arrival:before {
  content: "\f5af"
}

.fa-arrow-alt-circle-left:before,
.fa-circle-left:before {
  content: "\f359"
}

.fa-subway:before,
.fa-train-subway:before {
  content: "\f239"
}

.fa-chart-gantt:before {
  content: "\e0e4"
}

.fa-indian-rupee-sign:before,
.fa-indian-rupee:before,
.fa-inr:before {
  content: "\e1bc"
}

.fa-crop-alt:before,
.fa-crop-simple:before {
  content: "\f565"
}

.fa-money-bill-1:before,
.fa-money-bill-alt:before {
  content: "\f3d1"
}

.fa-left-long:before,
.fa-long-arrow-alt-left:before {
  content: "\f30a"
}

.fa-dna:before {
  content: "\f471"
}

.fa-virus-slash:before {
  content: "\e075"
}

.fa-minus:before,
.fa-subtract:before {
  content: "\f068"
}

.fa-child-rifle:before {
  content: "\e4e0"
}

.fa-chess:before {
  content: "\f439"
}

.fa-arrow-left-long:before,
.fa-long-arrow-left:before {
  content: "\f177"
}

.fa-plug-circle-check:before {
  content: "\e55c"
}

.fa-street-view:before {
  content: "\f21d"
}

.fa-franc-sign:before {
  content: "\e18f"
}

.fa-volume-off:before {
  content: "\f026"
}

.fa-american-sign-language-interpreting:before,
.fa-asl-interpreting:before,
.fa-hands-american-sign-language-interpreting:before,
.fa-hands-asl-interpreting:before {
  content: "\f2a3"
}

.fa-cog:before,
.fa-gear:before {
  content: "\f013"
}

.fa-droplet-slash:before,
.fa-tint-slash:before {
  content: "\f5c7"
}

.fa-mosque:before {
  content: "\f678"
}

.fa-mosquito:before {
  content: "\e52b"
}

.fa-star-of-david:before {
  content: "\f69a"
}

.fa-person-military-rifle:before {
  content: "\e54b"
}

.fa-cart-shopping:before,
.fa-shopping-cart:before {
  content: "\f07a"
}

.fa-vials:before {
  content: "\f493"
}

.fa-plug-circle-plus:before {
  content: "\e55f"
}

.fa-place-of-worship:before {
  content: "\f67f"
}

.fa-grip-vertical:before {
  content: "\f58e"
}

.fa-arrow-turn-up:before,
.fa-level-up:before {
  content: "\f148"
}

.fa-u:before {
  content: "\55"
}

.fa-square-root-alt:before,
.fa-square-root-variable:before {
  content: "\f698"
}

.fa-clock-four:before,
.fa-clock:before {
  content: "\f017"
}

.fa-backward-step:before,
.fa-step-backward:before {
  content: "\f048"
}

.fa-pallet:before {
  content: "\f482"
}

.fa-faucet:before {
  content: "\e005"
}

.fa-baseball-bat-ball:before {
  content: "\f432"
}

.fa-s:before {
  content: "\53"
}

.fa-timeline:before {
  content: "\e29c"
}

.fa-keyboard:before {
  content: "\f11c"
}

.fa-caret-down:before {
  content: "\f0d7"
}

.fa-clinic-medical:before,
.fa-house-chimney-medical:before {
  content: "\f7f2"
}

.fa-temperature-3:before,
.fa-temperature-three-quarters:before,
.fa-thermometer-3:before,
.fa-thermometer-three-quarters:before {
  content: "\f2c8"
}

.fa-mobile-android-alt:before,
.fa-mobile-screen:before {
  content: "\f3cf"
}

.fa-plane-up:before {
  content: "\e22d"
}

.fa-piggy-bank:before {
  content: "\f4d3"
}

.fa-battery-3:before,
.fa-battery-half:before {
  content: "\f242"
}

.fa-mountain-city:before {
  content: "\e52e"
}

.fa-coins:before {
  content: "\f51e"
}

.fa-khanda:before {
  content: "\f66d"
}

.fa-sliders-h:before,
.fa-sliders:before {
  content: "\f1de"
}

.fa-folder-tree:before {
  content: "\f802"
}

.fa-network-wired:before {
  content: "\f6ff"
}

.fa-map-pin:before {
  content: "\f276"
}

.fa-hamsa:before {
  content: "\f665"
}

.fa-cent-sign:before {
  content: "\e3f5"
}

.fa-flask:before {
  content: "\f0c3"
}

.fa-person-pregnant:before {
  content: "\e31e"
}

.fa-wand-sparkles:before {
  content: "\f72b"
}

.fa-ellipsis-v:before,
.fa-ellipsis-vertical:before {
  content: "\f142"
}

.fa-ticket:before {
  content: "\f145"
}

.fa-power-off:before {
  content: "\f011"
}

.fa-long-arrow-alt-right:before,
.fa-right-long:before {
  content: "\f30b"
}

.fa-flag-usa:before {
  content: "\f74d"
}

.fa-laptop-file:before {
  content: "\e51d"
}

.fa-teletype:before,
.fa-tty:before {
  content: "\f1e4"
}

.fa-diagram-next:before {
  content: "\e476"
}

.fa-person-rifle:before {
  content: "\e54e"
}

.fa-house-medical-circle-exclamation:before {
  content: "\e512"
}

.fa-closed-captioning:before {
  content: "\f20a"
}

.fa-hiking:before,
.fa-person-hiking:before {
  content: "\f6ec"
}

.fa-venus-double:before {
  content: "\f226"
}

.fa-images:before {
  content: "\f302"
}

.fa-calculator:before {
  content: "\f1ec"
}

.fa-people-pulling:before {
  content: "\e535"
}

.fa-n:before {
  content: "\4e"
}

.fa-cable-car:before,
.fa-tram:before {
  content: "\f7da"
}

.fa-cloud-rain:before {
  content: "\f73d"
}

.fa-building-circle-xmark:before {
  content: "\e4d4"
}

.fa-ship:before {
  content: "\f21a"
}

.fa-arrows-down-to-line:before {
  content: "\e4b8"
}

.fa-download:before {
  content: "\f019"
}

.fa-face-grin:before,
.fa-grin:before {
  content: "\f580"
}

.fa-backspace:before,
.fa-delete-left:before {
  content: "\f55a"
}

.fa-eye-dropper-empty:before,
.fa-eye-dropper:before,
.fa-eyedropper:before {
  content: "\f1fb"
}

.fa-file-circle-check:before {
  content: "\e5a0"
}

.fa-forward:before {
  content: "\f04e"
}

.fa-mobile-android:before,
.fa-mobile-phone:before,
.fa-mobile:before {
  content: "\f3ce"
}

.fa-face-meh:before,
.fa-meh:before {
  cont
Download .txt
gitextract_y_x3cf17/

├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.sbt
├── project/
│   ├── MdocSitePlugin.scala
│   ├── build.properties
│   └── plugins.sbt
└── src/
    ├── main/
    │   └── mdoc/
    │       ├── _adts/
    │       │   ├── data_constructors_in_companion_object.md
    │       │   ├── enumerations_as_adt.md
    │       │   ├── errors_extend_exception.md
    │       │   ├── final_case_objects.md
    │       │   ├── index.md
    │       │   └── product_with_serializable.md
    │       ├── _binary_compat/
    │       │   ├── abstract_over_trait.md
    │       │   ├── explicit_type_annotations.md
    │       │   └── index.md
    │       ├── _definitions/
    │       │   ├── adt.md
    │       │   ├── binary_compatibility.md
    │       │   ├── final.md
    │       │   ├── implicit_scope.md
    │       │   ├── paren-less.md
    │       │   ├── recursion.md
    │       │   ├── reference_equality.md
    │       │   ├── referential_transparency.md
    │       │   ├── sealed.md
    │       │   ├── tail_recursion.md
    │       │   ├── total_function.md
    │       │   └── type_class.md
    │       ├── _oop/
    │       │   ├── abstract_fields_as_defs.md
    │       │   ├── always_override.md
    │       │   └── index.md
    │       ├── _partial_functions/
    │       │   ├── either_projection_get.md
    │       │   ├── index.md
    │       │   ├── option_get.md
    │       │   ├── traversable_head.md
    │       │   ├── traversable_init.md
    │       │   ├── traversable_last.md
    │       │   ├── traversable_reduce.md
    │       │   ├── traversable_tail.md
    │       │   └── try_get.md
    │       ├── _referential_transparency/
    │       │   ├── avoid_mutability.md
    │       │   ├── avoid_return.md
    │       │   ├── avoid_throwing_exceptions.md
    │       │   └── index.md
    │       ├── _tricky_behaviours/
    │       │   ├── final_case_classes.md
    │       │   ├── future_in_comprehensions.md
    │       │   ├── implicit_shadowing.md
    │       │   ├── index.md
    │       │   ├── leaky_sealed_types.md
    │       │   ├── string_concatenation.md
    │       │   ├── type_implicits.md
    │       │   └── unicode_operators.md
    │       ├── _unsafe/
    │       │   ├── array_comparison.md
    │       │   ├── avoid_null.md
    │       │   ├── checking_empty_collection.md
    │       │   ├── custom_extractors.md
    │       │   ├── implicit_conversions.md
    │       │   ├── index.md
    │       │   ├── recursion.md
    │       │   ├── structural_types.md
    │       │   └── tail_recursion.md
    │       ├── _warming_up/
    │       │   ├── checking_for_nan.md
    │       │   ├── checking_for_odd.md
    │       │   ├── index.md
    │       │   └── numeric_literals.md
    │       └── index.md
    └── site/
        ├── _config.yml
        ├── _includes/
        │   ├── footer.html
        │   ├── header.html
        │   ├── linters.html
        │   └── toc.html
        ├── _layouts/
        │   ├── article.html
        │   ├── compress.html
        │   ├── definition.html
        │   ├── index.html
        │   └── section.html
        ├── css/
        │   ├── fira_code/
        │   │   └── fira_code.css
        │   ├── fontawesome/
        │   │   └── font-awesome.css
        │   ├── inter/
        │   │   └── inter.css
        │   └── styles.css
        └── fonts/
            ├── fira/
            │   ├── LICENSE
            │   ├── fira.css
            │   └── otf/
            │       ├── FiraMono-Bold.otf
            │       ├── FiraMono-Medium.otf
            │       └── FiraMono-Regular.otf
            └── fontawesome/
                ├── FontAwesome.otf
                └── font-awesome.css
Condensed preview — 88 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (311K chars).
[
  {
    "path": ".gitignore",
    "chars": 328,
    "preview": "*.class\n*.log\n\n# sbt specific\n.cache/\n.history/\n.lib/\ndist/*\ntarget/\nlib_managed/\nsrc_managed/\nproject/boot/\nproject/plu"
  },
  {
    "path": ".travis.yml",
    "chars": 362,
    "preview": "language: scala\ndist: trusty\nsudo: false\ncache:\n  directories:\n    - $HOME/.ivy2/cache\n    - $HOME/.sbt/boot/\n    - $HOM"
  },
  {
    "path": "LICENSE",
    "chars": 18646,
    "preview": "Attribution 4.0 International\n\n=======================================================================\n\nCreative Commons"
  },
  {
    "path": "README.md",
    "chars": 715,
    "preview": "# Building the site\n\n## Required tools\n\nThe following tools are needed to build the site:\n* [sbt], to compile and assemb"
  },
  {
    "path": "build.sbt",
    "chars": 604,
    "preview": "enablePlugins(MdocSitePlugin, GhpagesPlugin)\n\nscalaVersion              :=  \"2.12.8\"\nscalacOptions             ++= Seq(\""
  },
  {
    "path": "project/MdocSitePlugin.scala",
    "chars": 971,
    "preview": "import com.typesafe.sbt.site.SitePlugin.autoImport._\nimport mdoc.MdocPlugin, MdocPlugin.autoImport._\nimport sbt._, Keys."
  },
  {
    "path": "project/build.properties",
    "chars": 18,
    "preview": "sbt.version=1.2.6\n"
  },
  {
    "path": "project/plugins.sbt",
    "chars": 177,
    "preview": "addSbtPlugin(\"org.scalameta\"    % \"sbt-mdoc\"    % \"1.2.7\")\naddSbtPlugin(\"com.typesafe.sbt\" % \"sbt-site\"    % \"1.3.2\")\nad"
  },
  {
    "path": "src/main/mdoc/_adts/data_constructors_in_companion_object.md",
    "chars": 2369,
    "preview": "---\ntitle: Declare ADT data constructors in the companion object\nlayout: article\n---\n\n> When writing the various data co"
  },
  {
    "path": "src/main/mdoc/_adts/enumerations_as_adt.md",
    "chars": 1252,
    "preview": "---\ntitle: Use ADTs to implement enumerations\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: En"
  },
  {
    "path": "src/main/mdoc/_adts/errors_extend_exception.md",
    "chars": 3051,
    "preview": "---\ntitle: Make error ADTs subtypes of Exception\nlayout: article\n---\n\n> When creating an [ADT] to represent errors, have"
  },
  {
    "path": "src/main/mdoc/_adts/final_case_objects.md",
    "chars": 1307,
    "preview": "---\ntitle: Mark case objects as final\nlayout: article\n---\n\n> When declaring a case object, make it [`final`].\n\n# Reason\n"
  },
  {
    "path": "src/main/mdoc/_adts/index.md",
    "chars": 362,
    "preview": "---\nlayout: section\n---\n\n[ADTs][adt] are a common and powerful way of representing data. Scala encodes them in a way tha"
  },
  {
    "path": "src/main/mdoc/_adts/product_with_serializable.md",
    "chars": 1646,
    "preview": "---\ntitle: Make ADTs subtypes of Product and Serializable\nlayout: article\n---\n\n> When writing an [ADT], always have the "
  },
  {
    "path": "src/main/mdoc/_binary_compat/abstract_over_trait.md",
    "chars": 1837,
    "preview": "---\ntitle: Prefer abstract classes to traits\nlayout: article\n---\n\n> When declaring an abstract type without a clear reas"
  },
  {
    "path": "src/main/mdoc/_binary_compat/explicit_type_annotations.md",
    "chars": 2480,
    "preview": "---\ntitle: Add explicit type annotations to public members\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n   "
  },
  {
    "path": "src/main/mdoc/_binary_compat/index.md",
    "chars": 455,
    "preview": "---\nlayout: section\n---\n\n[Binary compatibility][bincompat] is a matter of some importance to library authors - breaking "
  },
  {
    "path": "src/main/mdoc/_definitions/adt.md",
    "chars": 3053,
    "preview": "---\ntitle: Algebraic Data Types\nlayout: definition\n---\n\nAlgebraic Data Types (ADTs for short) are a way of structuring d"
  },
  {
    "path": "src/main/mdoc/_definitions/binary_compatibility.md",
    "chars": 849,
    "preview": "---\ntitle: Binary compatibility\nlayout: definition\n---\n\nTwo versions of a library are said to be binary compatible if yo"
  },
  {
    "path": "src/main/mdoc/_definitions/final.md",
    "chars": 249,
    "preview": "---\ntitle: Final types\nlayout: definition\n---\n\nMarking a type as `final` means that it can never have subtypes.\n\nFor exa"
  },
  {
    "path": "src/main/mdoc/_definitions/implicit_scope.md",
    "chars": 844,
    "preview": "---\ntitle: Implicit scope\nlayout: definition\n---\n\nThe implicit scope of a type `T` is where the compiler will look when "
  },
  {
    "path": "src/main/mdoc/_definitions/paren-less.md",
    "chars": 408,
    "preview": "---\ntitle: Paren-less methods\nlayout: definition\n---\n\nA paren-less method is a method that doesn't take parameters (a nu"
  },
  {
    "path": "src/main/mdoc/_definitions/recursion.md",
    "chars": 336,
    "preview": "---\ntitle: Recursion\nlayout: definition\n---\n\nA recursive function is one that calls itself. For example:\n\n```scala mdoc\n"
  },
  {
    "path": "src/main/mdoc/_definitions/reference_equality.md",
    "chars": 799,
    "preview": "---\ntitle: Reference equality\nlayout: definition\n---\n\nReference equality is an equality relationship that does not only "
  },
  {
    "path": "src/main/mdoc/_definitions/referential_transparency.md",
    "chars": 2161,
    "preview": "---\ntitle: Referential transparency\nlayout: definition\n---\n\nAn expression is said to be referentially transparent if it "
  },
  {
    "path": "src/main/mdoc/_definitions/sealed.md",
    "chars": 528,
    "preview": "---\ntitle: Sealed types\nlayout: definition\n---\n\nMarking a type as `sealed` means that it can only have direct subtypes t"
  },
  {
    "path": "src/main/mdoc/_definitions/tail_recursion.md",
    "chars": 863,
    "preview": "---\ntitle: Tail recursion\nlayout: definition\n---\n\nA tail recursive function is a [recursive] function where the recursiv"
  },
  {
    "path": "src/main/mdoc/_definitions/total_function.md",
    "chars": 780,
    "preview": "---\ntitle: Total functions\nlayout: definition\n---\n\nA function is said to be total if it's defined for it's entire domain"
  },
  {
    "path": "src/main/mdoc/_definitions/type_class.md",
    "chars": 2581,
    "preview": "---\ntitle: Type class\nlayout: definition\n---\n\nIn the context of Scala, a type class is a family of types that support a "
  },
  {
    "path": "src/main/mdoc/_oop/abstract_fields_as_defs.md",
    "chars": 1723,
    "preview": "---\ntitle: Declare abstract fields as paren-less methods\nlayout: article\n---\n\n> When declaring abstract fields in an abs"
  },
  {
    "path": "src/main/mdoc/_oop/always_override.md",
    "chars": 2318,
    "preview": "---\ntitle: Use override when implementing abstract members\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n   "
  },
  {
    "path": "src/main/mdoc/_oop/index.md",
    "chars": 369,
    "preview": "---\nlayout: section\n---\n\nWhile it should be fairly obvious by now that I lean more on the FP part of the Scala community"
  },
  {
    "path": "src/main/mdoc/_partial_functions/either_projection_get.md",
    "chars": 2077,
    "preview": "---\ntitle: Do not call get on an Either projection\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - nam"
  },
  {
    "path": "src/main/mdoc/_partial_functions/index.md",
    "chars": 337,
    "preview": "---\nlayout: section\n---\n\nScala, like a lot of other languages, sometimes takes shortcuts in its standard library to meet"
  },
  {
    "path": "src/main/mdoc/_partial_functions/option_get.md",
    "chars": 1191,
    "preview": "---\ntitle: Do not call get on an Option\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: OptionPa"
  },
  {
    "path": "src/main/mdoc/_partial_functions/traversable_head.md",
    "chars": 836,
    "preview": "---\ntitle: Avoid using head\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: TraversableOps\n     "
  },
  {
    "path": "src/main/mdoc/_partial_functions/traversable_init.md",
    "chars": 1152,
    "preview": "---\ntitle: Avoid using init\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: TraversableOps\n     "
  },
  {
    "path": "src/main/mdoc/_partial_functions/traversable_last.md",
    "chars": 844,
    "preview": "---\ntitle: Avoid using last\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: TraversableOps\n     "
  },
  {
    "path": "src/main/mdoc/_partial_functions/traversable_reduce.md",
    "chars": 876,
    "preview": "---\ntitle: Avoid using reduce\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: TraversableOps\n   "
  },
  {
    "path": "src/main/mdoc/_partial_functions/traversable_tail.md",
    "chars": 1121,
    "preview": "---\ntitle: Avoid using tail\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: TraversableOps\n     "
  },
  {
    "path": "src/main/mdoc/_partial_functions/try_get.md",
    "chars": 1404,
    "preview": "---\ntitle: Do not call get on an Try\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: TryPartial\n"
  },
  {
    "path": "src/main/mdoc/_referential_transparency/avoid_mutability.md",
    "chars": 2647,
    "preview": "---\ntitle: Avoid mutability\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: Var\n        url:  ht"
  },
  {
    "path": "src/main/mdoc/_referential_transparency/avoid_return.md",
    "chars": 2719,
    "preview": "---\ntitle: Do not use return\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: Return\n        url:"
  },
  {
    "path": "src/main/mdoc/_referential_transparency/avoid_throwing_exceptions.md",
    "chars": 2497,
    "preview": "---\ntitle: Do not throw exceptions\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: Throw\n       "
  },
  {
    "path": "src/main/mdoc/_referential_transparency/index.md",
    "chars": 638,
    "preview": "---\nlayout: section\n---\n\n[Referential transparency][reftrans] is a big deal in FP - it's basically the core of what func"
  },
  {
    "path": "src/main/mdoc/_tricky_behaviours/final_case_classes.md",
    "chars": 3440,
    "preview": "---\ntitle: Mark case classes as final\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: FinalCaseC"
  },
  {
    "path": "src/main/mdoc/_tricky_behaviours/future_in_comprehensions.md",
    "chars": 2528,
    "preview": "---\ntitle: Start independent Futures outside of a for-comprehension\nlayout: article\n---\n\n> When working with independent"
  },
  {
    "path": "src/main/mdoc/_tricky_behaviours/implicit_shadowing.md",
    "chars": 2511,
    "preview": "---\ntitle: Make implicit names as unique as possible\nlayout: article\n---\n\n> When declaring an implicit value or method, "
  },
  {
    "path": "src/main/mdoc/_tricky_behaviours/index.md",
    "chars": 260,
    "preview": "---\nlayout: section\n---\n\nThis section explores aspects of Scala that break reasonable expectations or cause cryptic comp"
  },
  {
    "path": "src/main/mdoc/_tricky_behaviours/leaky_sealed_types.md",
    "chars": 1202,
    "preview": "---\ntitle: Make subtypes of sealed types final\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: L"
  },
  {
    "path": "src/main/mdoc/_tricky_behaviours/string_concatenation.md",
    "chars": 1359,
    "preview": "---\ntitle: Do not concatenate Strings with +\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: Str"
  },
  {
    "path": "src/main/mdoc/_tricky_behaviours/type_implicits.md",
    "chars": 1485,
    "preview": "---\ntitle: Add explicit type annotations to implicits\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - "
  },
  {
    "path": "src/main/mdoc/_tricky_behaviours/unicode_operators.md",
    "chars": 1437,
    "preview": "---\ntitle: Avoid unicode versions of ASCII operators\nlayout: article\nlinters:\n  - name: scalastyle\n    rules:\n      - na"
  },
  {
    "path": "src/main/mdoc/_unsafe/array_comparison.md",
    "chars": 1584,
    "preview": "---\ntitle: Do not compare arrays with ==\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: ArrayEq"
  },
  {
    "path": "src/main/mdoc/_unsafe/avoid_null.md",
    "chars": 2362,
    "preview": "---\ntitle: Do not use null\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: \"Null\"\n        url:  "
  },
  {
    "path": "src/main/mdoc/_unsafe/checking_empty_collection.md",
    "chars": 1663,
    "preview": "---\ntitle: Do not compute the size of a collection to check for emptiness\nlayout: article\nlinters:\n  - name: scapegoat\n "
  },
  {
    "path": "src/main/mdoc/_unsafe/custom_extractors.md",
    "chars": 2753,
    "preview": "---\ntitle: Do not return Option from custom extractors\nlayout: article\n---\n\n> When defining a custom extractor that happ"
  },
  {
    "path": "src/main/mdoc/_unsafe/implicit_conversions.md",
    "chars": 1589,
    "preview": "---\ntitle: Avoid implicit conversions\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - name: ImplicitCo"
  },
  {
    "path": "src/main/mdoc/_unsafe/index.md",
    "chars": 316,
    "preview": "---\nlayout: section\n---\n\nWe're now tackling parts of Scala that are actively unsafe to use: misusing them will cause pro"
  },
  {
    "path": "src/main/mdoc/_unsafe/recursion.md",
    "chars": 2586,
    "preview": "---\ntitle: Make recursive functions tail-recursive\nlayout: article\nlinters:\n  - name: wartremover\n    rules:\n      - nam"
  },
  {
    "path": "src/main/mdoc/_unsafe/structural_types.md",
    "chars": 2658,
    "preview": "---\ntitle: Avoid structural types\nlayout: article\nlinters:\n  - name: scalastyle\n    rules:\n      - name: StructuralTypeC"
  },
  {
    "path": "src/main/mdoc/_unsafe/tail_recursion.md",
    "chars": 1348,
    "preview": "---\ntitle: Mark tail-recursive functions as such\nlayout: article\n---\n\n> Always annotate your [tail-recursive] function w"
  },
  {
    "path": "src/main/mdoc/_warming_up/checking_for_nan.md",
    "chars": 1788,
    "preview": "---\ntitle: Use isNaN when checking for NaN\nlayout: article\nlinters:\n  - name: linter\n    rules:\n      - name: UseIsNanNo"
  },
  {
    "path": "src/main/mdoc/_warming_up/checking_for_odd.md",
    "chars": 825,
    "preview": "---\ntitle: Compare remainder to 0 when checking for oddness\nlayout: article\nlinters:\n  - name: scapegoat\n    rules:\n    "
  },
  {
    "path": "src/main/mdoc/_warming_up/index.md",
    "chars": 431,
    "preview": "---\nlayout: section\n---\n\nThis first section presents a few simple, non-controversial rules, with the purpose of easing t"
  },
  {
    "path": "src/main/mdoc/_warming_up/numeric_literals.md",
    "chars": 1162,
    "preview": "---\ntitle: Use upper case numeric literal suffixes\nlayout: article\nlinters:\n  - name: scalastyle\n    rules:\n      - name"
  },
  {
    "path": "src/main/mdoc/index.md",
    "chars": 906,
    "preview": "---\nlayout: index\n---\n\n# Foreword\n\nI often find myself, both professionaly and otherwise, having to explain bits of Scal"
  },
  {
    "path": "src/site/_config.yml",
    "chars": 920,
    "preview": "name:        Scala Best Practices\nmarkdown:    kramdown\nhighlighter: rouge\nbaseurl:     /scala-best-practices\n\ncollectio"
  },
  {
    "path": "src/site/_includes/footer.html",
    "chars": 226,
    "preview": "\n<div id=\"footer\">\n  <hr>\n\n  <p class=\"wrapper\">\n    This work is licensed under a <a rel=\"license\" href=\"https://creati"
  },
  {
    "path": "src/site/_includes/header.html",
    "chars": 1443,
    "preview": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>{{ site.name }}{% if page.title %} - {{ page.title"
  },
  {
    "path": "src/site/_includes/linters.html",
    "chars": 1503,
    "preview": "<h1>Checked by</h1>\n{% if include.linters %}\n<table>\n  <thead>\n    <tr>\n      <th>Linter</th>\n      <th>Rule</th>\n    </"
  },
  {
    "path": "src/site/_includes/toc.html",
    "chars": 301,
    "preview": "{% assign sorted_pages = include.collection | sort: \"title\" %}\n<ul>\n{% for x in sorted_pages %}\n{% if x.title != \"Index\""
  },
  {
    "path": "src/site/_layouts/article.html",
    "chars": 228,
    "preview": "---\nlayout: compress\n---\n{% include header.html %}\n<div class=\"wrapper\">\n    {% if page.title %}<h1>{{ page.title }}</h1"
  },
  {
    "path": "src/site/_layouts/compress.html",
    "chars": 4491,
    "preview": "---\n# Jekyll layout that compresses HTML\n# v3.0.4\n# http://jch.penibelst.de/\n# © 2014–2015 Anatol Broder\n# MIT License\n-"
  },
  {
    "path": "src/site/_layouts/definition.html",
    "chars": 176,
    "preview": "---\nlayout: compress\n---\n{% include header.html %}\n<div class=\"wrapper\">\n    {% if page.title %}<h1>{{ page.title }}</h1"
  },
  {
    "path": "src/site/_layouts/index.html",
    "chars": 376,
    "preview": "---\nlayout: compress\n---\n{% include header.html %}\n<div class=\"wrapper index\">\n  {{ content }}\n\n  <h1>Table of Contents<"
  },
  {
    "path": "src/site/_layouts/section.html",
    "chars": 323,
    "preview": "---\nlayout: compress\n---\n{% include header.html %}\n\n{% for c in site.collections %}\n{% if c.label == page.collection %}\n"
  },
  {
    "path": "src/site/css/fira_code/fira_code.css",
    "chars": 835,
    "preview": "@font-face{\n    font-family: 'Fira Code';\n    src: url('woff2/FiraCode-Light.woff2') format('woff2'),\n         url('woff"
  },
  {
    "path": "src/site/css/fontawesome/font-awesome.css",
    "chars": 119627,
    "preview": "/*!\n * Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com\n * License - https://fontawesome.com/license/fr"
  },
  {
    "path": "src/site/css/inter/inter.css",
    "chars": 5246,
    "preview": "@font-face {\n  font-family: 'Inter';\n  font-style:  normal;\n  font-weight: 100;\n  font-display: swap;\n  src: url(\"woff2/"
  },
  {
    "path": "src/site/css/styles.css",
    "chars": 7595,
    "preview": "@import './inter/inter.css';\n@import './fira_code/fira_code.css';\n@import './fontawesome/font-awesome.css';\n\nbody {\n\tlin"
  },
  {
    "path": "src/site/fonts/fira/LICENSE",
    "chars": 4421,
    "preview": "Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.\nwith Reserved Font Name < Fira >, \n\nT"
  },
  {
    "path": "src/site/fonts/fira/fira.css",
    "chars": 696,
    "preview": "@font-face{\n    font-family: 'Fira Mono';\n    src: url('eot/FiraMono-Regular.eot');\n    src: local('Fira Mono'),\n       "
  },
  {
    "path": "src/site/fonts/fontawesome/font-awesome.css",
    "chars": 26669,
    "preview": "/*!\n *  Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome\n *  License - http://fontawesome.io/lice"
  }
]

// ... and 4 more files (download for full content)

About this extraction

This page contains the full source code of the nrinaudo/scala-best-practices GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 88 files (277.4 KB), approximately 87.1k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!