diff --git a/docs/docs/reference/changed-features/eta-expansion-spec.md b/docs/docs/reference/changed-features/eta-expansion-spec.md index 28ac11eef2e8..172c7c1be0be 100644 --- a/docs/docs/reference/changed-features/eta-expansion-spec.md +++ b/docs/docs/reference/changed-features/eta-expansion-spec.md @@ -73,4 +73,4 @@ The method value syntax `m _` is deprecated. ## Reference -For more info, see [PR #2701](https://github.com/lampepfl/dotty/pull/2701). +For more information, see [PR #2701](https://github.com/lampepfl/dotty/pull/2701). diff --git a/docs/docs/reference/changed-features/implicit-conversions-spec.md b/docs/docs/reference/changed-features/implicit-conversions-spec.md index df76c0b7dbfe..5df0f5f0ac46 100644 --- a/docs/docs/reference/changed-features/implicit-conversions-spec.md +++ b/docs/docs/reference/changed-features/implicit-conversions-spec.md @@ -119,4 +119,4 @@ Resolution](implicit-resolution.md) for more information. For more information about implicit resolution, see [Changes in Implicit Resolution](implicit-resolution.md). Other details are available in -[PR #2065](https://github.com/lampepfl/dotty/pull/2065) +[PR #2065](https://github.com/lampepfl/dotty/pull/2065). diff --git a/docs/docs/reference/changed-features/main-functions.md b/docs/docs/reference/changed-features/main-functions.md index 3a063a17b412..3fc00ce3da92 100644 --- a/docs/docs/reference/changed-features/main-functions.md +++ b/docs/docs/reference/changed-features/main-functions.md @@ -6,6 +6,7 @@ title: "Main Methods" Scala 3 offers a new way to define programs that can be invoked from the command line: A `@main` annotation on a method turns this method into an executable program. Example: + ```scala @main def happyBirthday(age: Int, name: String, others: String*) = val suffix = @@ -21,11 +22,14 @@ Example: for other <- others do bldr.append(" and ").append(other) bldr.toString ``` + This would generate a main program `happyBirthday` that could be called like this + ``` > scala happyBirthday 23 Lisa Peter Happy 23rd Birthday, Lisa and Peter! ``` + A `@main` annotated method can be written either at the top-level or in a statically accessible object. The name of the program is in each case the name of the method, without any object prefixes. The `@main` method can have an arbitrary number of parameters. For each parameter type there must be an instance of the `scala.util.FromString` type class that is used to convert an argument string to the required parameter type. @@ -52,9 +56,10 @@ The Scala compiler generates a program from a `@main` method `f` as follows: - The class has a static method `main` with the usual signature. It takes an `Array[String]` as argument and returns `Unit`. - The generated `main` method calls method `f` with arguments converted using - methods in the `scala.util.CommandLineParser` object. + methods in the [`scala.util.CommandLineParser` object](https://dotty.epfl.ch/api/scala/util/CommandLineParser$.html). For instance, the `happyBirthDay` method above would generate additional code equivalent to the following class: + ```scala final class happyBirthday: import scala.util.{CommandLineParser => CLP} @@ -67,6 +72,7 @@ final class happyBirthday: catch case error: CLP.ParseError => CLP.showError(error) ``` + **Note**: The `` modifier above expresses that the `main` method is generated as a static method of class `happyBirthDay`. It is not available for user programs in Scala. Regular "static" members are generated in Scala using objects instead. @@ -78,5 +84,5 @@ object happyBirthday extends App: ... ``` -The previous functionality of `App`, which relied on the "magic" `DelayedInit` trait, is no longer available. `App` still exists in limited form for now, but it does not support command line arguments and will be deprecated in the future. If programs need to cross-build +The previous functionality of `App`, which relied on the "magic" [`DelayedInit`](../dropped-features/delayed-init.md) trait, is no longer available. `App` still exists in limited form for now, but it does not support command line arguments and will be deprecated in the future. If programs need to cross-build between Scala 2 and Scala 3, it is recommended to use an explicit `main` method with an `Array[String]` argument instead. diff --git a/docs/docs/reference/changed-features/match-syntax.md b/docs/docs/reference/changed-features/match-syntax.md index ed4ec87e2380..440925b52643 100644 --- a/docs/docs/reference/changed-features/match-syntax.md +++ b/docs/docs/reference/changed-features/match-syntax.md @@ -1,6 +1,6 @@ --- layout: doc-page -title: Match Expressions +title: "Match Expressions" --- The syntactical precedence of match expressions has been changed. diff --git a/docs/docs/reference/changed-features/numeric-literals.md b/docs/docs/reference/changed-features/numeric-literals.md index 843c348fffa1..d9c9af042b54 100644 --- a/docs/docs/reference/changed-features/numeric-literals.md +++ b/docs/docs/reference/changed-features/numeric-literals.md @@ -1,14 +1,16 @@ --- layout: doc-page -title: Numeric Literals +title: "Numeric Literals" --- **Note**: This feature is not yet part of the Scala 3 language definition. It can be made available by a language import: + ```scala import scala.language.experimental.genericNumberLiterals ``` -In Scala 2, numeric literals were confined to the primitive numeric types `Int`, `Long`, `Float`, and `Double`. Scala 3 allows to write numeric literals also for user defined types. Example: +In Scala 2, numeric literals were confined to the primitive numeric types `Int`, `Long`, `Float`, and `Double`. Scala 3 allows to write numeric literals also for user-defined types. Example: + ```scala val x: Long = -10_000_000_000 val y: BigInt = 0x123_abc_789_def_345_678_901 @@ -17,6 +19,7 @@ val z: BigDecimal = 110_222_799_799.99 (y: BigInt) match case 123_456_789_012_345_678_901 => ``` + The syntax of numeric literals is the same as before, except there are no pre-set limits how large they can be. diff --git a/docs/docs/reference/changed-features/operators.md b/docs/docs/reference/changed-features/operators.md index d98da3bed317..50801f5aef7c 100644 --- a/docs/docs/reference/changed-features/operators.md +++ b/docs/docs/reference/changed-features/operators.md @@ -12,6 +12,7 @@ a syntax change allows infix operators to be written on the left in a multi-line ## The `infix` Modifier An `infix` modifier on a method definition allows using the method as an infix operation. Example: + ```scala import scala.annotation.targetName @@ -40,6 +41,7 @@ s1 * s2 // OK s1 `*` s2 // also OK, but unusual s1.*(s2) // also OK, but unusual ``` + Infix operations involving alphanumeric operators are deprecated, unless one of the following conditions holds: @@ -53,7 +55,8 @@ any Unicode character `c` for which `java.lang.Character.isIdentifierPart(c)` re Infix operations involving symbolic operators are always allowed, so `infix` is redundant for methods with symbolic names. The `infix` modifier can also be given to a type: -``` + +```scala infix type or[X, Y] val x: String or Int = ... ``` @@ -107,6 +110,7 @@ It is recommended that definitions of symbolic operators carry a [`@targetName` ## Syntax Change Infix operators can now appear at the start of lines in a multi-line expression. Examples: + ```scala val str = "hello" ++ " world" @@ -117,6 +121,7 @@ def condition = || xs.exists(_ > 0) || xs.isEmpty ``` + Previously, those expressions would have been rejected, since the compiler's semicolon inference would have treated the continuations `++ " world"` or `|| xs.isEmpty` as separate statements. @@ -133,19 +138,24 @@ Example: freezing | boiling ``` + This is recognized as a single infix operation. Compare with: + ```scala freezing !boiling ``` + This is seen as two statements, `freezing` and `!boiling`. The difference is that only the operator in the first example is followed by a space. Another example: + ```scala println("hello") ??? ??? match { case 0 => 1 } ``` + This code is recognized as three different statements. `???` is syntactically a symbolic identifier, but neither of its occurrences is followed by a space and a token that can start an expression. diff --git a/docs/docs/reference/changed-features/structural-types-spec.md b/docs/docs/reference/changed-features/structural-types-spec.md index 489dd795bc9d..4de11e2d5d50 100644 --- a/docs/docs/reference/changed-features/structural-types-spec.md +++ b/docs/docs/reference/changed-features/structural-types-spec.md @@ -30,9 +30,11 @@ the methods `selectDynamic` and `applyDynamic`. The methods could be members of The `selectDynamic` method takes a field name and returns the value associated with that name in the `Selectable`. It should have a signature of the form: + ```scala def selectDynamic(name: String): T ``` + Often, the return type `T` is `Any`. Unlike `scala.Dynamic`, there is no special meaning for an `updateDynamic` method. @@ -41,10 +43,12 @@ Consequently, it is recommended not to define any member called `updateDynamic` The `applyDynamic` method is used for selections that are applied to arguments. It takes a method name and possibly `Class`es representing its parameters types as well as the arguments to pass to the function. Its signature should be of one of the two following forms: + ```scala def applyDynamic(name: String)(args: Any*): T def applyDynamic(name: String, ctags: Class[?]*)(args: Any*): T ``` + Both versions are passed the actual arguments in the `args` parameter. The second version takes in addition a vararg argument of `java.lang.Class`es that identify the method's parameter classes. Such an argument is needed if `applyDynamic` is implemented using Java reflection, but it could be useful in other cases as well. `selectDynamic` and `applyDynamic` can also take additional context parameters in using clauses. These are resolved in the normal way at the callsite. @@ -94,5 +98,4 @@ conversion that can turn `v` into a `Selectable`, and the selection methods coul ## Context -For more info, see [Rethink Structural -Types](https://github.com/lampepfl/dotty/issues/1886). +For more information, see [Rethink Structural Types](https://github.com/lampepfl/dotty/issues/1886). diff --git a/docs/docs/reference/changed-features/structural-types.md b/docs/docs/reference/changed-features/structural-types.md index 0ffbd3f37f8f..9a056fb2beee 100644 --- a/docs/docs/reference/changed-features/structural-types.md +++ b/docs/docs/reference/changed-features/structural-types.md @@ -32,6 +32,7 @@ configure how fields and methods should be resolved. ## Example Here's an example of a structural type `Person`: + ```scala class Record(elems: (String, Any)*) extends Selectable: private val fields = elems.toMap @@ -39,12 +40,15 @@ Here's an example of a structural type `Person`: type Person = Record { val name: String; val age: Int } ``` + The type `Person` adds a _refinement_ to its parent type `Record` that defines the two fields `name` and `age`. We say the refinement is _structural_ since `name` and `age` are not defined in the parent type. But they exist nevertheless as members of class `Person`. For instance, the following program would print "Emma is 42 years old.": + ```scala val person = Record("name" -> "Emma", "age" -> 42).asInstanceOf[Person] println(s"${person.name} is ${person.age} years old.") ``` + The parent type `Record` in this example is a generic class that can represent arbitrary records in its `elems` argument. This argument is a sequence of pairs of labels of type `String` and values of type `Any`. When we create a `Person` as a `Record` we have to assert with a typecast @@ -59,12 +63,14 @@ a method `selectDynamic`, which maps a field name to its value. Selecting a structural type member is done by calling this method. The `person.name` and `person.age` selections are translated by the Scala compiler to: + ```scala person.selectDynamic("name").asInstanceOf[String] person.selectDynamic("age").asInstanceOf[Int] ``` Besides `selectDynamic`, a `Selectable` class sometimes also defines a method `applyDynamic`. This can then be used to translate function calls of structural members. So, if `a` is an instance of `Selectable`, a structural call like `a.f(b, c)` would translate to + ```scala a.applyDynamic("f")(b, c) ``` @@ -72,6 +78,7 @@ Besides `selectDynamic`, a `Selectable` class sometimes also defines a method `a ## Using Java Reflection Structural types can also be accessed using [Java reflection](https://www.oracle.com/technical-resources/articles/java/javareflection.html). Example: + ```scala type Closeable = { def close(): Unit } @@ -81,14 +88,17 @@ Structural types can also be accessed using [Java reflection](https://www.oracle class Channel: def close(): Unit ``` + Here, we define a structural type `Closeable` that defines a `close` method. There are various classes that have `close` methods, we just list `FileInputStream` and `Channel` as two examples. It would be easiest if the two classes shared a common interface that factors out the `close` method. But such factorings are often not possible if different libraries are combined in one application. Yet, we can still have methods that work on all classes with a `close` method by using the `Closeable` type. For instance, + ```scala import scala.reflect.Selectable.reflectiveSelectable def autoClose(f: Closeable)(op: Closeable => Unit): Unit = try op(f) finally f.close() ``` + The call `f.close()` has to use Java reflection to identify and call the `close` method in the receiver `f`. This needs to be enabled by an import of `reflectiveSelectable` shown above. What happens "under the hood" is then the following: @@ -122,6 +132,7 @@ the database access example given at the beginning of this document. Local and anonymous classes that extend `Selectable` get more refined types than other classes. Here is an example: + ```scala trait Vehicle extends reflect.Selectable: val wheels: Int @@ -132,12 +143,14 @@ val i3 = new Vehicle: // i3: Vehicle { val range: Int } i3.range ``` + The type of `i3` in this example is `Vehicle { val range: Int }`. Hence, `i3.range` is well-formed. Since the base class `Vehicle` does not define a `range` field or method, we need structural dispatch to access the `range` field of the anonymous class that initializes `id3`. Structural dispatch is implemented by the base trait `reflect.Selectable` of `Vehicle`, which defines the necessary `selectDynamic` member. `Vehicle` could also extend some other subclass of `scala.Selectable` that implements `selectDynamic` and `applyDynamic` differently. But if it does not extend a `Selectable` at all, the code would no longer typecheck: + ```scala trait Vehicle: val wheels: Int @@ -148,6 +161,7 @@ val i3 = new Vehicle: // i3: Vehicle i3.range // error: range is not a member of `Vehicle` ``` + The difference is that the type of an anonymous class that does not extend `Selectable` is just formed from the parent type(s) of the class, without adding any refinements. Hence, `i3` now has just type `Vehicle` and the selection `i3.range` gives a "member not found" error. diff --git a/docs/docs/reference/changed-features/type-checking.md b/docs/docs/reference/changed-features/type-checking.md index b167a37c44cc..4c9d1f6139b9 100644 --- a/docs/docs/reference/changed-features/type-checking.md +++ b/docs/docs/reference/changed-features/type-checking.md @@ -3,4 +3,4 @@ layout: doc-page title: "Changes in Type Checking" --- -[//]: # todo: fill in +*** **TO BE FILLED IN** *** diff --git a/docs/docs/reference/changed-features/type-inference.md b/docs/docs/reference/changed-features/type-inference.md index 226063912244..b1cd806c0999 100644 --- a/docs/docs/reference/changed-features/type-inference.md +++ b/docs/docs/reference/changed-features/type-inference.md @@ -3,4 +3,7 @@ layout: doc-page title: "Changes in Type Inference" --- -See https://www.youtube.com/watch?v=lMvOykNQ4zs, https://www.youtube.com/watch?v=VV9lPg3fNl8. +For more information, see the two presentations + +* [Scala 3, Type inference and You!](https://www.youtube.com/watch?v=lMvOykNQ4zs) by Guillaume Martres (September 2019) +* [GADTs in Dotty](https://www.youtube.com/watch?v=VV9lPg3fNl8) by Aleksander Boruch-Gruszecki (July 2019). diff --git a/docs/docs/reference/changed-features/wildcards.md b/docs/docs/reference/changed-features/wildcards.md index 38db6174ae43..a17d283bc9af 100644 --- a/docs/docs/reference/changed-features/wildcards.md +++ b/docs/docs/reference/changed-features/wildcards.md @@ -17,7 +17,8 @@ for the type lambda `[X] =>> C[X]`. This makes higher-kinded types easier to use parameter, `F[_]` means `F` is a type constructor whereas used as a type, `F[_]` means it is a wildcard (i.e. existential) type. In the future, `F[_]` will mean the same thing, no matter where it is used. -We pick `?` as a replacement syntax for wildcard types, since it aligns with Java's syntax. +We pick `?` as a replacement syntax for wildcard types, since it aligns with +[Java's syntax](https://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html). ### Migration Strategy @@ -40,4 +41,4 @@ option `-Ykind-projector`: available to rewrite one to the other. 3. In Scala 3.3, `*` is removed again, and all type parameter placeholders will be expressed with `_`. -These rules make it possible to cross build between Scala 2 using the kind projector plugin and Scala 3.0 - 3.2 using option `-Ykind-projector`. +These rules make it possible to cross build between Scala 2 using the kind projector plugin and Scala 3.0 - 3.2 using the compiler option `-Ykind-projector`. diff --git a/docs/docs/reference/contextual/by-name-context-parameters.md b/docs/docs/reference/contextual/by-name-context-parameters.md index 868ab8a3f08f..549cdb4e08b7 100644 --- a/docs/docs/reference/contextual/by-name-context-parameters.md +++ b/docs/docs/reference/contextual/by-name-context-parameters.md @@ -35,6 +35,7 @@ The precise steps for synthesizing an argument for a by-name context parameter o ```scala given lv: T = ??? ``` + where `lv` is an arbitrary fresh name. 1. This given is not immediately available as candidate for argument inference (making it immediately available could result in a loop in the synthesized computation). But it becomes available in all nested contexts that look again for an argument to a by-name context parameter. @@ -51,7 +52,7 @@ In the example above, the definition of `s` would be expanded as follows. ```scala val s = summon[Test.Codec[Option[Int]]]( - optionCodec[Int](using intCodec) + optionCodec[Int](using intCodec) ) ``` @@ -59,5 +60,5 @@ No local given instance was generated because the synthesized argument is not re ### Reference -For more info, see [Issue #1998](https://github.com/lampepfl/dotty/issues/1998) +For more information, see [Issue #1998](https://github.com/lampepfl/dotty/issues/1998) and the associated [Scala SIP](https://docs.scala-lang.org/sips/byname-implicits.html). diff --git a/docs/docs/reference/contextual/context-functions-spec.md b/docs/docs/reference/contextual/context-functions-spec.md index 1f212c299d4b..d5e1eaa61ca7 100644 --- a/docs/docs/reference/contextual/context-functions-spec.md +++ b/docs/docs/reference/contextual/context-functions-spec.md @@ -5,10 +5,12 @@ title: "Context Functions - More Details" ## Syntax - Type ::= ... - | FunArgTypes ‘?=>’ Type - Expr ::= ... - | FunParams ‘?=>’ Expr +``` +Type ::= ... + | FunArgTypes ‘?=>’ Type +Expr ::= ... + | FunParams ‘?=>’ Expr +``` Context function types associate to the right, e.g. `S ?=> T ?=> U` is the same as `S ?=> (T ?=> U)`. @@ -19,11 +21,13 @@ Context function types are shorthands for class types that define `apply` methods with context parameters. Specifically, the `N`-ary function type `T1, ..., TN => R` is a shorthand for the class type `ContextFunctionN[T1 , ... , TN, R]`. Such class types are assumed to have the following definitions, for any value of `N >= 1`: + ```scala package scala trait ContextFunctionN[-T1 , ... , -TN, +R]: def apply(using x1: T1 , ... , xN: TN): R ``` + Context function types erase to normal function types, so these classes are generated on the fly for typechecking, but not realized in actual code. @@ -40,17 +44,18 @@ The type of the context function literal is `scala.ContextFunctionN[S1, ...,Sn, type of `e`. `T` must be equivalent to a type which does not refer to any of the context parameters `xi`. -The context function literal is evaluated as the instance creation -expression +The context function literal is evaluated as the instance creation expression + ```scala new scala.ContextFunctionN[T1, ..., Tn, T]: def apply(using x1: T1, ..., xn: Tn): T = e ``` + A context parameter may also be a wildcard represented by an underscore `_`. In that case, a fresh name for the parameter is chosen arbitrarily. Note: The closing paragraph of the -[Anonymous Functions section](https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#anonymous-functions) -of Scala 2.12 is subsumed by context function types and should be removed. +[Anonymous Functions section](https://www.scala-lang.org/files/archive/spec/2.13/06-expressions.html#anonymous-functions) +of Scala 2.13 is subsumed by context function types and should be removed. Context function literals `(x1: T1, ..., xn: Tn) ?=> e` are automatically created for any expression `e` whose expected type is diff --git a/docs/docs/reference/contextual/context-functions.md b/docs/docs/reference/contextual/context-functions.md index 284f07485a98..46b7ffa539ae 100644 --- a/docs/docs/reference/contextual/context-functions.md +++ b/docs/docs/reference/contextual/context-functions.md @@ -148,7 +148,7 @@ val s = ``` ### Reference -For more info, see the [blog article](https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html), +For more information, see the [blog article](https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html), (which uses a different syntax that has been superseded). [More details](./context-functions-spec.md) diff --git a/docs/docs/reference/contextual/derivation.md b/docs/docs/reference/contextual/derivation.md index fea8c3355e57..6c8b59125333 100644 --- a/docs/docs/reference/contextual/derivation.md +++ b/docs/docs/reference/contextual/derivation.md @@ -1,6 +1,6 @@ --- layout: doc-page -title: Type Class Derivation +title: "Type Class Derivation" --- Type class derivation is a way to automatically generate given instances for type classes which satisfy some simple diff --git a/docs/docs/reference/contextual/extension-methods.md b/docs/docs/reference/contextual/extension-methods.md index e7bddf6dbc21..6a0a2eac0375 100644 --- a/docs/docs/reference/contextual/extension-methods.md +++ b/docs/docs/reference/contextual/extension-methods.md @@ -186,7 +186,7 @@ object IntOpsEx extends IntOps: trait SafeDiv: import IntOpsEx._ // brings safeDiv and safeMod into scope - extension (i: Int) def divide(d: Int) : Option[(Int, Int)] = + extension (i: Int) def divide(d: Int): Option[(Int, Int)] = // extension methods imported and thus in scope (i.safeDiv(d), i.safeMod(d)) match case (Some(d), Some(r)) => Some((d, r)) diff --git a/docs/docs/reference/contextual/givens.md b/docs/docs/reference/contextual/givens.md index 738a2d3e0f29..95cb2969782d 100644 --- a/docs/docs/reference/contextual/givens.md +++ b/docs/docs/reference/contextual/givens.md @@ -66,7 +66,7 @@ use named instances. ## Alias Givens -An alias can be used to define a given instance that is equal to some expression. E.g.: +An alias can be used to define a given instance that is equal to some expression. Example: ```scala given global: ExecutionContext = ForkJoinPool() diff --git a/docs/docs/reference/contextual/relationship-implicits.md b/docs/docs/reference/contextual/relationship-implicits.md index c9a0020fbf63..f79d3204200a 100644 --- a/docs/docs/reference/contextual/relationship-implicits.md +++ b/docs/docs/reference/contextual/relationship-implicits.md @@ -143,7 +143,7 @@ Implicit by-name parameters are not supported in Scala 2, but can be emulated to ### Implicit Conversions -Implicit conversion methods in Scala 2 can be expressed as given instances of the `scala.Conversion` class in Scala 3. E.g. instead of +Implicit conversion methods in Scala 2 can be expressed as given instances of the `scala.Conversion` class in Scala 3. For instance, instead of ```scala implicit def stringToToken(str: String): Token = new Keyword(str) @@ -169,7 +169,7 @@ Implicit classes in Scala 2 are often used to define extension methods, which ar ### Implicit Values Implicit `val` definitions in Scala 2 can be expressed in Scala 3 using a regular `val` definition and an alias given. -E.g., Scala 2's +For instance, Scala 2's ```scala lazy implicit val pos: Position = tree.sourcePos @@ -184,7 +184,7 @@ given Position = pos ### Abstract Implicits -An abstract implicit `val` or `def` in Scala 2 can be expressed in Scala 3 using a regular abstract definition and an alias given. E.g., Scala 2's +An abstract implicit `val` or `def` in Scala 2 can be expressed in Scala 3 using a regular abstract definition and an alias given. For instance, Scala 2's ```scala implicit def symDecorator: SymDecorator @@ -199,7 +199,7 @@ given SymDecorator = symDecorator ## Implementation Status and Timeline -The Scala 3 implementation implements both Scala 2's implicits and the new abstractions. In fact, support for Scala 2's implicits is an essential part of the common language subset between 2.13/2.14 and Scala 3. +The Scala 3 implementation implements both Scala 2's implicits and the new abstractions. In fact, support for Scala 2's implicits is an essential part of the common language subset between 2.13 and Scala 3. Migration to the new abstractions will be supported by making automatic rewritings available. Depending on adoption patterns, old style implicits might start to be deprecated in a version following Scala 3.0. diff --git a/docs/docs/reference/contextual/using-clauses.md b/docs/docs/reference/contextual/using-clauses.md index f5ae506c80b1..e76ad8b71693 100644 --- a/docs/docs/reference/contextual/using-clauses.md +++ b/docs/docs/reference/contextual/using-clauses.md @@ -10,16 +10,21 @@ repetitive arguments instead of the programmer having to write them explicitly. For example, with the [given instances](./givens.md) defined previously, a `max` function that works for any arguments for which an ordering exists can be defined as follows: + ```scala def max[T](x: T, y: T)(using ord: Ord[T]): T = if ord.compare(x, y) < 0 then y else x ``` + Here, `ord` is a _context parameter_ introduced with a `using` clause. The `max` function can be applied as follows: + ```scala max(2, 3)(using intOrd) ``` + The `(using intOrd)` part passes `intOrd` as an argument for the `ord` parameter. But the point of context parameters is that this argument can also be left out (and it usually is). So the following applications are equally valid: + ```scala max(2, 3) max(List(1, 2, 3), Nil) @@ -31,10 +36,12 @@ In many situations, the name of a context parameter need not be mentioned explicitly at all, since it is used only in synthesized arguments for other context parameters. In that case one can avoid defining a parameter name and just provide its type. Example: + ```scala def maximum[T](xs: List[T])(using Ord[T]): T = xs.reduceLeft(max) ``` + `maximum` takes a context parameter of type `Ord` only to pass it on as an inferred argument to `max`. The name of the parameter is left out. @@ -43,6 +50,7 @@ Generally, context parameters may be defined either as a full parameter list `(p ## Inferring Complex Arguments Here are two other methods that have a context parameter of type `Ord[T]`: + ```scala def descending[T](using asc: Ord[T]): Ord[T] = new Ord[T]: def compare(x: T, y: T) = asc.compare(y, x) @@ -50,8 +58,10 @@ def descending[T](using asc: Ord[T]): Ord[T] = new Ord[T]: def minimum[T](xs: List[T])(using Ord[T]) = maximum(xs)(using descending) ``` + The `minimum` method's right hand side passes `descending` as an explicit argument to `maximum(xs)`. With this setup, the following calls are all well-formed, and they all normalize to the last one: + ```scala minimum(xs) maximum(xs)(using descending) @@ -62,22 +72,28 @@ maximum(xs)(using descending(using listOrd(using intOrd))) ## Multiple `using` Clauses There can be several `using` clauses in a definition and `using` clauses can be freely mixed with normal parameter clauses. Example: + ```scala def f(u: Universe)(using ctx: u.Context)(using s: ctx.Symbol, k: ctx.Kind) = ... ``` + Multiple `using` clauses are matched left-to-right in applications. Example: + ```scala object global extends Universe { type Context = ... } given ctx : global.Context with { type Symbol = ...; type Kind = ... } given sym : ctx.Symbol given kind: ctx.Kind + ``` Then the following calls are all valid (and normalize to the last one) + ```scala f(global) f(global)(using ctx) f(global)(using ctx)(using sym, kind) ``` + But `f(global)(using sym, kind)` would give a type error. @@ -85,10 +101,13 @@ But `f(global)(using sym, kind)` would give a type error. The method `summon` in `Predef` returns the given of a specific type. For example, the given instance for `Ord[List[Int]]` is produced by + ```scala summon[Ord[List[Int]]] // reduces to listOrd(using intOrd) ``` + The `summon` method is simply defined as the (non-widening) identity function over a context parameter. + ```scala def summon[T](using x: T): x.type = x ``` @@ -96,6 +115,7 @@ def summon[T](using x: T): x.type = x ## Syntax Here is the new syntax of parameters and arguments seen as a delta from the [standard context free syntax of Scala 3](../syntax.md). `using` is a soft keyword, recognized only at the start of a parameter or argument list. It can be used as a normal identifier everywhere else. + ``` ClsParamClause ::= ... | UsingClsParamClause DefParamClauses ::= ... | UsingParamClause diff --git a/docs/docs/reference/dropped-features/auto-apply.md b/docs/docs/reference/dropped-features/auto-apply.md index d7bbab69329b..9ff9aa648502 100644 --- a/docs/docs/reference/dropped-features/auto-apply.md +++ b/docs/docs/reference/dropped-features/auto-apply.md @@ -5,28 +5,36 @@ title: "Dropped: Auto-Application" Previously an empty argument list `()` was implicitly inserted when calling a nullary method without arguments. Example: + ```scala def next(): T = ... next // is expanded to next() ``` + In Scala 3, this idiom is an error. + ```scala next ^ missing arguments for method next ``` + In Scala 3, the application syntax has to follow exactly the parameter syntax. Excluded from this rule are methods that are defined in Java or that override methods defined in Java. The reason for being more lenient with such methods is that otherwise everyone would have to write + ```scala xs.toString().length() ``` + instead of + ```scala xs.toString.length ``` + The latter is idiomatic Scala because it conforms to the _uniform access principle_. This principle states that one should be able to change an object member from a field to a non-side-effecting method @@ -47,9 +55,11 @@ the correspondence between definition and call was not enforced in Scala so far, there are quite a few method definitions in Scala 2 libraries that use `()` in an inconsistent way. For instance, we find in `scala.math.Numeric` + ```scala def toInt(): Int ``` + whereas `toInt` is written without parameters everywhere else. Enforcing strict parameter correspondence for references to such methods would project the inconsistencies to client code, which @@ -61,12 +71,15 @@ Stricter conformance rules also apply to overriding of nullary methods. It is no longer allowed to override a parameterless method by a nullary method or _vice versa_. Instead, both methods must agree exactly in their parameter lists. + ```scala class A: def next(): Int + class B extends A: def next: Int // overriding error: incompatible type ``` + Methods overriding Java or Scala 2 methods are again exempted from this requirement. @@ -79,4 +92,4 @@ stricter checking. ### Reference -For more info, see [Issue #2570](https://github.com/lampepfl/dotty/issues/2570) and [PR #2716](https://github.com/lampepfl/dotty/pull/2716). +For more information, see [Issue #2570](https://github.com/lampepfl/dotty/issues/2570) and [PR #2716](https://github.com/lampepfl/dotty/pull/2716). diff --git a/docs/docs/reference/dropped-features/class-shadowing.md b/docs/docs/reference/dropped-features/class-shadowing.md index a733273fc0ed..d1d92a47bcbc 100644 --- a/docs/docs/reference/dropped-features/class-shadowing.md +++ b/docs/docs/reference/dropped-features/class-shadowing.md @@ -4,6 +4,7 @@ title: "Dropped: Class Shadowing" --- Scala 2 so far allowed patterns like this: + ```scala class Base { class Ops { ... } @@ -13,12 +14,16 @@ class Sub extends Base { class Ops { ... } } ``` + Scala 3 rejects this with the error message: + ```scala 6 | class Ops { } | ^ - |class Ops cannot have the same name as class Ops in class Base -- class definitions cannot be overridden + |class Ops cannot have the same name as class Ops in class Base + | -- class definitions cannot be overridden ``` + The issue is that the two `Ops` classes _look_ like one overrides the other, but classes in Scala 2 cannot be overridden. To keep things clean (and its internal operations consistent) the Scala 3 compiler forces you diff --git a/docs/docs/reference/dropped-features/delayed-init.md b/docs/docs/reference/dropped-features/delayed-init.md index fd115ab08db0..ca640185252d 100644 --- a/docs/docs/reference/dropped-features/delayed-init.md +++ b/docs/docs/reference/dropped-features/delayed-init.md @@ -3,24 +3,27 @@ layout: doc-page title: "Dropped: Delayedinit" --- -The special handling of the `DelayedInit` trait is no longer -supported. +The special handling of the `DelayedInit` trait is no longer supported. One consequence is that the `App` class, which used `DelayedInit` is now partially broken. You can still use `App` as a simple way to set up a main program. Example: + ```scala object HelloWorld extends App { - println("Hello, world!") + println("Hello, world!") } ``` + However, the code is now run in the initializer of the object, which on some JVM's means that it will only be interpreted. So, better not use it for benchmarking! Also, if you want to access the command line arguments, you need to use an explicit `main` method for that. + ```scala object Hello: def main(args: Array[String]) = println(s"Hello, ${args(0)}") ``` + On the other hand, Scala 3 offers a convenient alternative to such "program" objects -with [@main methods](../changed-features/main-functions.html). +with [`@main` methods](../changed-features/main-functions.md). diff --git a/docs/docs/reference/dropped-features/macros.md b/docs/docs/reference/dropped-features/macros.md index aaf180ee7e84..ca8d2adfb345 100644 --- a/docs/docs/reference/dropped-features/macros.md +++ b/docs/docs/reference/dropped-features/macros.md @@ -12,4 +12,4 @@ Additionally, the contents of code can be inspected and created with a more comp * `inline` has been [implemented](../metaprogramming/inline.md) in Scala 3. * Quotes `'{ ... }` and splices `${ ... }` has been [implemented](../metaprogramming/macros.md) in Scala 3. - * [TASTy reflect](../metaprogramming/tasty-reflect.md) provides more complex tree based APIs to inspect or create quoted code. +* [TASTy reflect](../metaprogramming/tasty-reflect.md) provides more complex tree based APIs to inspect or create quoted code. diff --git a/docs/docs/reference/dropped-features/nonlocal-returns.md b/docs/docs/reference/dropped-features/nonlocal-returns.md index e3af0d1de2d1..9ef49c635c84 100644 --- a/docs/docs/reference/dropped-features/nonlocal-returns.md +++ b/docs/docs/reference/dropped-features/nonlocal-returns.md @@ -7,10 +7,19 @@ Returning from nested anonymous functions has been deprecated. Nonlocal returns are implemented by throwing and catching `scala.runtime.NonLocalReturnException`-s. This is rarely what is intended by the programmer. It can be problematic because of the hidden performance cost of throwing and catching exceptions. Furthermore, it is a leaky implementation: a catch-all exception handler can intercept a `NonLocalReturnException`. -A drop-in library replacement is provided in `scala.util.control.NonLocalReturns`: +A drop-in library replacement is provided in [`scala.util.control.NonLocalReturns`](http://dotty.epfl.ch/api/scala/util/control/NonLocalReturns$.html). Example: ```scala import scala.util.control.NonLocalReturns._ -returning { ... throwReturn(x) ... } +extension [T](xs: List[T]) + def has(elem: T): Boolean = returning { + for x <- xs do + if x == elem then throwReturn(true) + false + } + +@main def test = + val xs = List(1, 2, 3, 4, 5) + assert(xs.has(2) == xs.contains(2)) ``` diff --git a/docs/docs/reference/enums/adts.md b/docs/docs/reference/enums/adts.md index f12d53c97cd0..6bfb188b349d 100644 --- a/docs/docs/reference/enums/adts.md +++ b/docs/docs/reference/enums/adts.md @@ -98,12 +98,15 @@ below: The following `View` enum has a contravariant type parameter `T` and a single case `Refl`, representing a function mapping a type `T` to itself: + ```scala enum View[-T]: case Refl(f: T => T) ``` + The definition of `Refl` is incorrect, as it uses contravariant type `T` in the covariant result position of a function type, leading to the following error: + ```scala -- Error: View.scala:2:12 -------- 2 | case Refl(f: T => T) @@ -111,7 +114,9 @@ function type, leading to the following error: |contravariant type T occurs in covariant position in type T => T of value f |enum case Refl requires explicit declaration of type T to resolve this issue. ``` + Because `Refl` does not declare explicit parameters, it looks to the compiler like the following: + ```scala enum View[-T]: case Refl[/*synthetic*/-T1](f: T1 => T1) extends View[T1] @@ -126,6 +131,7 @@ enum View[-T]: - case Refl(f: T => T) + case Refl[R](f: R => R) extends View[R] ``` + Above, type `R` is chosen as the parameter for `Refl` to highlight that it has a different meaning to type `T` in `View`, but any name will do. @@ -163,4 +169,4 @@ The changes are specified below as deltas with respect to the Scala syntax given ### Reference -For more info, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970). +For more information, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970). diff --git a/docs/docs/reference/enums/enums.md b/docs/docs/reference/enums/enums.md index 278036272731..fff3c721f163 100644 --- a/docs/docs/reference/enums/enums.md +++ b/docs/docs/reference/enums/enums.md @@ -144,5 +144,5 @@ val Red: Color = $new(0, "Red") ### Reference -For more info, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970) and +For more information, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970) and [PR #4003](https://github.com/lampepfl/dotty/pull/4003). diff --git a/docs/docs/reference/features-classification.md b/docs/docs/reference/features-classification.md index 70fe386323ec..1b729987a980 100644 --- a/docs/docs/reference/features-classification.md +++ b/docs/docs/reference/features-classification.md @@ -34,12 +34,12 @@ Since these are additions, there's generally no migration cost for old code. An These constructs replace existing constructs with the aim of making the language safer and simpler to use, and to promote uniformity in code style. - - [Trait Parameters](other-new-features/trait-parameters.md) replace [early initializers](dropped-features/early-initializers.md) with a more generally useful construct. - - [Given Instances](contextual/givens.md) + - [Trait parameters](other-new-features/trait-parameters.md) replace [early initializers](dropped-features/early-initializers.md) with a more generally useful construct. + - [Given instances](contextual/givens.md) replace implicit objects and defs, focussing on intent over mechanism. - [Using Clauses](contextual/using-clauses.md) replace implicit parameters, avoiding their ambiguities. - - [Extension Methods](contextual/extension-methods.md) replace implicit classes with a clearer and simpler mechanism. - - [Opaque Type Aliases](other-new-features/opaques.md) replace most uses + - [Extension methods](contextual/extension-methods.md) replace implicit classes with a clearer and simpler mechanism. + - [Opaque type aliases](other-new-features/opaques.md) replace most uses of value classes while guaranteeing absence of boxing. - [Top-level definitions](dropped-features/package-objects.md) replace package objects, dropping syntactic boilerplate. - [Export clauses](other-new-features/export.md) diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index bb87d7792a18..ba18f55d76d8 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -623,5 +623,5 @@ transparent inline def summonInline[T]: T = summonFrom { ### Reference -For more info, see [PR #4768](https://github.com/lampepfl/dotty/pull/4768), +For more information, see [PR #4768](https://github.com/lampepfl/dotty/pull/4768), which explains how `summonFrom`'s predecessor (implicit matches) can be used for typelevel programming and code specialization and [PR #7201](https://github.com/lampepfl/dotty/pull/7201) which explains the new `summonFrom` syntax. diff --git a/docs/docs/reference/metaprogramming/macros.md b/docs/docs/reference/metaprogramming/macros.md index eb443338d9df..a91767fc3fe6 100644 --- a/docs/docs/reference/metaprogramming/macros.md +++ b/docs/docs/reference/metaprogramming/macros.md @@ -158,9 +158,11 @@ is legal because it is spliced, then quoted. They can be used as follows: ```scala -val f1: Expr[Int => String] = to((x: Expr[Int]) => '{ $x.toString }) // '{ (x: Int) => x.toString } +val f1: Expr[Int => String] = + to((x: Expr[Int]) => '{ $x.toString }) // '{ (x: Int) => x.toString } -val f2: Expr[Int] => Expr[String] = from('{ (x: Int) => x.toString }) // (x: Expr[Int]) => '{ ((x: Int) => x.toString)($x) } +val f2: Expr[Int] => Expr[String] = + from('{ (x: Int) => x.toString }) // (x: Expr[Int]) => '{ ((x: Int) => x.toString)($x) } f2('{2}) // '{ ((x: Int) => x.toString)(2) } ``` diff --git a/docs/docs/reference/metaprogramming/tasty-inspect.md b/docs/docs/reference/metaprogramming/tasty-inspect.md index a1657fdc6c20..a9abfd48b12f 100644 --- a/docs/docs/reference/metaprogramming/tasty-inspect.md +++ b/docs/docs/reference/metaprogramming/tasty-inspect.md @@ -4,7 +4,7 @@ title: "TASTy Inspection" --- ```scala -libraryDependencies += "ch.epfl.lamp" %% "scala3-tasty-inspector" % scalaVersion.value +libraryDependencies += "org.scala-lang" %% "scala3-tasty-inspector" % scalaVersion.value ``` TASTy files contain the full typed tree of a class including source positions diff --git a/docs/docs/reference/new-types/dependent-function-types-spec.md b/docs/docs/reference/new-types/dependent-function-types-spec.md index 48f3102c8890..944fec44ff86 100644 --- a/docs/docs/reference/new-types/dependent-function-types-spec.md +++ b/docs/docs/reference/new-types/dependent-function-types-spec.md @@ -3,7 +3,7 @@ layout: doc-page title: "Dependent Function Types - More Details" --- -Initial implementation in [#3464](https://github.com/lampepfl/dotty/pull/3464) +Initial implementation in [PR #3464](https://github.com/lampepfl/dotty/pull/3464). ## Syntax @@ -37,8 +37,8 @@ one of regular functions. Eta expansion is naturally generalized to produce dependent function types for methods with dependent result types. Dependent functions can be implicit, and generalize to arity `N > 22` in the -same way that other functions do, see [the corresponding -documentation](../dropped-features/limit22.md). +same way that other functions do, see +[the corresponding documentation](../dropped-features/limit22.md). ## Examples diff --git a/docs/docs/reference/new-types/dependent-function-types.md b/docs/docs/reference/new-types/dependent-function-types.md index 8e7a79ae2b37..8374c9c41794 100644 --- a/docs/docs/reference/new-types/dependent-function-types.md +++ b/docs/docs/reference/new-types/dependent-function-types.md @@ -5,6 +5,7 @@ title: "Dependent Function Types" A dependent function type is a function type whose result depends on the function's parameters. For example: + ```scala trait Entry { type Key; val key: Key } @@ -14,6 +15,7 @@ val extractor: (e: Entry) => e.Key = extractKey // a dependent function value // ^^^^^^^^^^^^^^^^^^^ // a dependent function type ``` + Scala already has _dependent methods_, i.e. methods where the result type refers to some of the parameters of the method. Method `extractKey` is an example. Its result type, `e.Key` refers to its @@ -37,8 +39,10 @@ instance of the `Function1` trait (i.e. `Function1[A, B]`) and analogously for functions with more parameters. Dependent functions are also represented as instances of these traits, but they get an additional refinement. In fact, the dependent function type above is just syntactic sugar for + ```scala Function1[Entry, Entry#Key]: def apply(e: Entry): e.Key ``` + [More details](./dependent-function-types-spec.md) diff --git a/docs/docs/reference/new-types/intersection-types-spec.md b/docs/docs/reference/new-types/intersection-types-spec.md index e4b92388e2db..1ad0ed62601d 100644 --- a/docs/docs/reference/new-types/intersection-types-spec.md +++ b/docs/docs/reference/new-types/intersection-types-spec.md @@ -84,20 +84,20 @@ below in pseudocode: ``` |S & T| = glb(|S|, |T|) -glb(JArray(A), JArray(B)) = JArray(glb(A, B)) -glb(JArray(T), _) = JArray(T) -glb(_, JArray(T)) = JArray(T) -glb(A, B) = A if A extends B -glb(A, B) = B if B extends A -glb(A, _) = A if A is not a trait -glb(_, B) = B if B is not a trait -glb(A, _) = A // use first +glb(JArray(A), JArray(B)) = JArray(glb(A, B)) +glb(JArray(T), _) = JArray(T) +glb(_, JArray(T)) = JArray(T) +glb(A, B) = A if A extends B +glb(A, B) = B if B extends A +glb(A, _) = A if A is not a trait +glb(_, B) = B if B is not a trait +glb(A, _) = A // use first ``` In the above, `|T|` means the erased type of `T`, `JArray` refers to the type of Java Array. -See also: `TypeErasure#erasedGlb` +See also: [`TypeErasure#erasedGlb`](https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/TypeErasure.scala#L289). ## Relationship with Compound Type (`with`) diff --git a/docs/docs/reference/new-types/polymorphic-function-types.md b/docs/docs/reference/new-types/polymorphic-function-types.md index 9b6abb9b6dd5..1be8baca17ad 100644 --- a/docs/docs/reference/new-types/polymorphic-function-types.md +++ b/docs/docs/reference/new-types/polymorphic-function-types.md @@ -5,6 +5,7 @@ title: "Polymorphic Function Types" A polymorphic function type is a function type which accepts type parameters. For example: + ```scala // A polymorphic method: def foo[A](xs: List[A]): List[A] = xs.reverse @@ -15,6 +16,7 @@ val bar: [A] => List[A] => List[A] // a polymorphic function type = [A] => (xs: List[A]) => foo[A](xs) ``` + Scala already has _polymorphic methods_, i.e. methods which accepts type parameters. Method `foo` above is an example, accepting a type parameter `A`. So far, it diff --git a/docs/docs/reference/new-types/union-types-spec.md b/docs/docs/reference/new-types/union-types-spec.md index ad1fe6b8f57e..4349c136bd60 100644 --- a/docs/docs/reference/new-types/union-types-spec.md +++ b/docs/docs/reference/new-types/union-types-spec.md @@ -15,11 +15,15 @@ lower precedence than `:` as used in typed patterns, this means that: ```scala case _: A | B => ... ``` + is still equivalent to: + ```scala case (_: A) | B => ... ``` + and not to: + ```scala case _: (A | B) => ... ``` @@ -29,18 +33,21 @@ case _: (A | B) => ... - `A` is always a subtype of `A | B` for all `A`, `B`. - If `A <: C` and `B <: C` then `A | B <: C` - Like `&`, `|` is commutative and associative: + ```scala A | B =:= B | A A | (B | C) =:= (A | B) | C ``` + - `&` is distributive over `|`: + ```scala A & (B | C) =:= A & B | A & C ``` From these rules it follows that the _least upper bound_ (LUB) of a set of types is the union of these types. This replaces the -[definition of least upper bound in the Scala 2 specification](https://www.scala-lang.org/files/archive/spec/2.12/03-types.html#least-upper-bounds-and-greatest-lower-bounds). +[definition of least upper bound in the Scala 2 specification](https://www.scala-lang.org/files/archive/spec/2.13/03-types.html#least-upper-bounds-and-greatest-lower-bounds). ## Motivation @@ -92,9 +99,10 @@ which are "too precise" can lead to unintuitive typechecking issues later on. Note: Since this behavior limits the usability of union types, it might be changed in the future. For example by not widening unions that have been explicitly written down by the user and not inferred, or by not widening a type -argument when the corresponding type parameter is covariant. See -[#2330](https://github.com/lampepfl/dotty/pull/2330) and -[#4867](https://github.com/lampepfl/dotty/issues/4867) for further discussions. +argument when the corresponding type parameter is covariant. + +See [PR #2330](https://github.com/lampepfl/dotty/pull/2330) and +[Issue #4867](https://github.com/lampepfl/dotty/issues/4867) for further discussions. ### Example diff --git a/docs/docs/reference/other-new-features/explicit-nulls.md b/docs/docs/reference/other-new-features/explicit-nulls.md index a651107f59d6..b05055c5c26a 100644 --- a/docs/docs/reference/other-new-features/explicit-nulls.md +++ b/docs/docs/reference/other-new-features/explicit-nulls.md @@ -11,10 +11,10 @@ This means the following code will no longer typecheck: val x: String = null // error: found `Null`, but required `String` ``` -Instead, to mark a type as nullable we use a [union type](https://dotty.epfl.ch/docs/reference/new-types/union-types.html) +Instead, to mark a type as nullable we use a [union type](../new-types/union-types.md) ```scala -val x: String|Null = null // ok +val x: String | Null = null // ok ``` Explicit nulls are enabled via a `-Yexplicit-nulls` flag. @@ -37,6 +37,7 @@ After erasure, `Null` remains a subtype of all reference types (as forced by the The new type system is unsound with respect to `null`. This means there are still instances where an expression has a non-nullable type like `String`, but its value is actually `null`. The unsoundness happens because uninitialized fields in a class start out as `null`: + ```scala class C: val f: String = foo(f) diff --git a/docs/docs/reference/other-new-features/export.md b/docs/docs/reference/other-new-features/export.md index b770cbf99c03..b5b8c71e2c2b 100644 --- a/docs/docs/reference/other-new-features/export.md +++ b/docs/docs/reference/other-new-features/export.md @@ -4,6 +4,7 @@ title: "Export Clauses" --- An export clause defines aliases for selected members of an object. Example: + ```scala class BitMap class InkJet @@ -26,22 +27,29 @@ class Copier: def status: List[String] = printUnit.status ++ scanUnit.status ``` + The two `export` clauses define the following _export aliases_ in class `Copier`: + ```scala final def scan(): BitMap = scanUnit.scan() final def print(bits: BitMap): Unit = printUnit.print(bits) final type PrinterType = printUnit.PrinterType ``` + They can be accessed inside `Copier` as well as from outside: + ```scala val copier = new Copier copier.print(copier.scan()) ``` + An export clause has the same format as an import clause. Its general form is: + ```scala export path . { sel_1, ..., sel_n } export given path . { sel_1, ..., sel_n } ``` + It consists of a qualifier expression `path`, which must be a stable identifier, followed by one or more selectors `sel_i` that identify what gets an alias. Selectors can be of one of the following forms: @@ -93,7 +101,7 @@ Export clauses can appear in classes or they can appear at the top-level. An exp It is a standard recommendation to prefer composition over inheritance. This is really an application of the principle of least power: Composition treats components as blackboxes whereas inheritance can affect the internal workings of components through overriding. Sometimes the close coupling implied by inheritance is the best solution for a problem, but where this is not necessary the looser coupling of composition is better. -So far, object oriented languages including Scala made it much easier to use inheritance than composition. Inheritance only requires an `extends` clause whereas composition required a verbose elaboration of a sequence of forwarders. So in that sense, object-oriented languages are pushing +So far, object-oriented languages including Scala made it much easier to use inheritance than composition. Inheritance only requires an `extends` clause whereas composition required a verbose elaboration of a sequence of forwarders. So in that sense, object-oriented languages are pushing programmers to a solution that is often too powerful. Export clauses redress the balance. They make composition relationships as concise and easy to express as inheritance relationships. Export clauses also offer more flexibility than extends clauses since members can be renamed or omitted. Export clauses also fill a gap opened by the shift from package objects to top-level definitions. One occasionally useful idiom that gets lost in this shift is a package object inheriting from some class. The idiom is often used in a facade like pattern, to make members @@ -114,17 +122,21 @@ Export ::= ‘export’ [‘given’] ImportExpr {‘,’ ImportExpr} Export clauses raise questions about the order of elaboration during type checking. Consider the following example: + ```scala class B { val c: Int } object a { val b = new B } export a._ export b._ ``` + Is the `export b._` clause legal? If yes, what does it export? Is it equivalent to `export a.b._`? What about if we swap the last two clauses? + ``` export b._ export a._ ``` + To avoid tricky questions like these, we fix the elaboration order of exports as follows. Export clauses are processed when the type information of the enclosing object or class is completed. Completion so far consisted of the following steps: diff --git a/docs/docs/reference/other-new-features/indentation.md b/docs/docs/reference/other-new-features/indentation.md index 6c5d6a3617f9..2ebbe817b9ea 100644 --- a/docs/docs/reference/other-new-features/indentation.md +++ b/docs/docs/reference/other-new-features/indentation.md @@ -83,9 +83,9 @@ There are two rules: - the first token on the next line is not a [leading infix operator](../changed-features/operators.md). - If an `` is inserted, the top element is popped from `IW`. - If the indentation width of the token on the next line is still less than the new current indentation width, step (2) repeats. Therefore, several `` tokens - may be inserted in a row. + If an `` is inserted, the top element is popped from `IW`. + If the indentation width of the token on the next line is still less than the new current indentation width, step (2) repeats. Therefore, several `` tokens + may be inserted in a row. An `` is also inserted if the next token following a statement sequence starting with an `` closes an indentation region, i.e. is one of `then`, `else`, `do`, `catch`, `finally`, `yield`, `}`, `)`, `]` or `case`. @@ -134,9 +134,11 @@ new A: package p: def a = 1 + package q: def b = 2 ``` + In each case, the `:` at the end of line can be replaced without change of meaning by a pair of braces that enclose the following indented definition(s). The syntax changes allowing this are as follows: @@ -356,7 +358,7 @@ Significant indentation is enabled by default. It can be turned off by giving an The Scala 3 compiler can rewrite source code to indented code and back. When invoked with options `-rewrite -indent` it will rewrite braces to indented regions where possible. When invoked with options `-rewrite -noindent` it will rewrite in the reverse direction, inserting braces for indentation regions. -The `-indent` option only works on [new-style syntax](./control-syntax.html). So to go from old-style syntax to new-style indented code one has to invoke the compiler twice, first with options `-rewrite -new-syntax`, then again with options +The `-indent` option only works on [new-style syntax](./control-syntax.md). So to go from old-style syntax to new-style indented code one has to invoke the compiler twice, first with options `-rewrite -new-syntax`, then again with options `-rewrite -indent`. To go in the opposite direction, from indented code to old-style syntax, it's `-rewrite -noindent`, followed by `-rewrite -old-syntax`. ### Variant: Indentation Marker `:` diff --git a/docs/docs/reference/other-new-features/opaques-details.md b/docs/docs/reference/other-new-features/opaques-details.md index 723d319e2f3e..af7483d9f799 100644 --- a/docs/docs/reference/other-new-features/opaques-details.md +++ b/docs/docs/reference/other-new-features/opaques-details.md @@ -9,6 +9,7 @@ title: "Opaque Type Aliases: More Details" Modifier ::= ... | ‘opaque’ ``` + `opaque` is a [soft modifier](../soft-modifier.md). It can still be used as a normal identifier when it is not in front of a definition keyword. Opaque type aliases must be members of classes, traits, or objects, or they are defined @@ -17,9 +18,11 @@ at the top-level. They cannot be defined in local blocks. ### Type Checking The general form of a (monomorphic) opaque type alias is + ```scala opaque type T >: L <: U = R ``` + where the lower bound `L` and the upper bound `U` may be missing, in which case they are assumed to be `scala.Nothing` and `scala.Any`, respectively. If bounds are given, it is checked that the right hand side `R` conforms to them, i.e. `L <: R` and `R <: U`. F-bounds are not supported for opaque type aliases: `T` is not allowed to appear in `L` or `U`. Inside the scope of the alias definition, the alias is transparent: `T` is treated @@ -28,15 +31,18 @@ as a normal alias of `R`. Outside its scope, the alias is treated as the abstrac type T >: L <: U ``` A special case arises if the opaque type alias is defined in an object. Example: -``` + +```scala object o: opaque type T = R ``` + In this case we have inside the object (also for non-opaque types) that `o.T` is equal to `T` or its expanded form `o.this.T`. Equality is understood here as mutual subtyping, i.e. `o.T <: o.this.T` and `o.this.T <: T`. Furthermore, we have by the rules of opaque type aliases that `o.this.T` equals `R`. The two equalities compose. That is, inside `o`, it is also known that `o.T` is equal to `R`. This means the following code type-checks: + ```scala object o: opaque type T = Int diff --git a/docs/docs/reference/other-new-features/parameter-untupling-spec.md b/docs/docs/reference/other-new-features/parameter-untupling-spec.md index 42ca89ed5361..21e1aebd6a12 100644 --- a/docs/docs/reference/other-new-features/parameter-untupling-spec.md +++ b/docs/docs/reference/other-new-features/parameter-untupling-spec.md @@ -13,6 +13,7 @@ val xs: List[(Int, Int)] and you want to map `xs` to a list of `Int`s so that each pair of numbers is mapped to their sum. Previously, the best way to do this was with a pattern-matching decomposition: + ```scala xs.map { case (x, y) => x + y @@ -25,7 +26,9 @@ xs.map { (x, y) => x + y } ``` + or, equivalently: + ```scala xs.map(_ + _) ``` @@ -51,6 +54,7 @@ can in turn be adapted to the expected type with auto-tupling. #### Term adaptation If the function + ```scala (p1: T1, ..., pn: Tn) => e ``` @@ -75,9 +79,9 @@ Translation of such a tuples would use the `apply` method on the tuple to access Code like this could not be written before, hence the new notation would not be ambiguous after adoption. Though it is possible that someone has written an implicit conversion form `(T1, ..., Tn) => R` to `TupleN[T1, ..., Tn] => R` -for some `n`. This change could be detected and fixed by `Scalafix`. Furthermore, such conversion would probably +for some `n`. This change could be detected and fixed by [`Scalafix`](https://scalacenter.github.io/scalafix/). Furthermore, such conversion would probably be doing the same translation (semantically) but in a less efficient way. ### Reference -For more info see [Issue #897](https://github.com/lampepfl/dotty/issues/897). +For more information, see [Issue #897](https://github.com/lampepfl/dotty/issues/897). diff --git a/docs/docs/reference/other-new-features/parameter-untupling.md b/docs/docs/reference/other-new-features/parameter-untupling.md index 24400f178e34..5f8f322c5126 100644 --- a/docs/docs/reference/other-new-features/parameter-untupling.md +++ b/docs/docs/reference/other-new-features/parameter-untupling.md @@ -4,34 +4,42 @@ title: "Parameter Untupling" --- Say you have a list of pairs + ```scala val xs: List[(Int, Int)] ``` + and you want to map `xs` to a list of `Int`s so that each pair of numbers is mapped to their sum. Previously, the best way to do this was with a pattern-matching decomposition: + ```scala xs map { case (x, y) => x + y } ``` + While correct, this is also inconvenient and confusing, since the `case` suggests that the pattern match could fail. As a shorter and clearer alternative Scala 3 now allows + ```scala xs.map { (x, y) => x + y } ``` + or, equivalently: + ```scala xs.map(_ + _) ``` + Generally, a function value with `n > 1` parameters is converted to a pattern-matching closure using `case` if the expected type is a unary function type of the form `((T_1, ..., T_n)) => U`. -### Reference +## Reference -For more info see: +For more information see: * [More details](./parameter-untupling-spec.md) * [Issue #897](https://github.com/lampepfl/dotty/issues/897). diff --git a/docs/docs/reference/other-new-features/trait-parameters.md b/docs/docs/reference/other-new-features/trait-parameters.md index c82c1e225f1c..1655e338b32c 100644 --- a/docs/docs/reference/other-new-features/trait-parameters.md +++ b/docs/docs/reference/other-new-features/trait-parameters.md @@ -54,4 +54,4 @@ class E extends Greeting("Bob"), FormalGreeting ## Reference -For more info, see [Scala SIP 25](http://docs.scala-lang.org/sips/pending/trait-parameters.html). +For more information, see [Scala SIP 25](http://docs.scala-lang.org/sips/pending/trait-parameters.html). diff --git a/docs/docs/reference/overview.md b/docs/docs/reference/overview.md index 38c27f0622d1..6cd62f39edcd 100644 --- a/docs/docs/reference/overview.md +++ b/docs/docs/reference/overview.md @@ -36,7 +36,7 @@ These constructs replace existing constructs with the aim of making the language - [Given instances](contextual/givens.md) replace implicit objects and defs, focussing on intent over mechanism. - [Using clauses](contextual/using-clauses.md) replace implicit parameters, avoiding their ambiguities. - - [Extension Methods](contextual/extension-methods.md) replace implicit classes with a clearer and simpler mechanism. + - [Extension methods](contextual/extension-methods.md) replace implicit classes with a clearer and simpler mechanism. - [Opaque type aliases](other-new-features/opaques.md) replace most uses of value classes while guaranteeing absence of boxing. - [Top-level definitions](dropped-features/package-objects.md) replace package objects, dropping syntactic boilerplate. @@ -107,11 +107,11 @@ Most aspects of old-style implicit resolution are still available under `-source These are additions to the language that make it more powerful or pleasant to use. - [Enums](enums/enums.md) provide concise syntax for enumerations and [algebraic data types](enums/adts.md). - - [Parameter Untupling](other-new-features/parameter-untupling.md) avoids having to use `case` for tupled parameter destructuring. - - [Dependent Function Types](new-types/dependent-function-types.md) generalize dependent methods to dependent function values and types. - - [Polymorphic Function Types](new-types/polymorphic-function-types.md) generalize polymorphic methods to polymorphic function values and types. _Current status_: There is a proposal and a merged prototype implementation, but the implementation has not been finalized (it is notably missing type inference support). - - [Kind Polymorphism](other-new-features/kind-polymorphism.md) allows the definition of operators working equally on types and type constructors. - - [`@targetName` Annotations](other-new-features/targetName.md) make it easier to interoperate with code written in other languages and give more flexibility for avoiding name clashes. + - [Parameter untupling](other-new-features/parameter-untupling.md) avoids having to use `case` for tupled parameter destructuring. + - [Dependent function types](new-types/dependent-function-types.md) generalize dependent methods to dependent function values and types. + - [Polymorphic function types](new-types/polymorphic-function-types.md) generalize polymorphic methods to polymorphic function values and types. _Current status_: There is a proposal and a merged prototype implementation, but the implementation has not been finalized (it is notably missing type inference support). + - [Kind polymorphism](other-new-features/kind-polymorphism.md) allows the definition of operators working equally on types and type constructors. + - [`@targetName` annotations](other-new-features/targetName.md) make it easier to interoperate with code written in other languages and give more flexibility for avoiding name clashes. ## Metaprogramming diff --git a/docs/docs/reference/syntax.md b/docs/docs/reference/syntax.md index 6764ed477179..b37ecf514a1c 100644 --- a/docs/docs/reference/syntax.md +++ b/docs/docs/reference/syntax.md @@ -28,9 +28,9 @@ letter ::= upper | lower “… and Unicode categories Lo, Lt, Nl” digit ::= ‘0’ | … | ‘9’ paren ::= ‘(’ | ‘)’ | ‘[’ | ‘]’ | ‘{’ | ‘}’ | ‘'(’ | ‘'[’ | ‘'{’ delim ::= ‘`’ | ‘'’ | ‘"’ | ‘.’ | ‘;’ | ‘,’ -opchar ::= “printableChar not matched by (whiteSpace | upper | lower | - letter | digit | paren | delim | opchar | Unicode_Sm | - Unicode_So)” +opchar ::= “printableChar not matched by (whiteSpace | upper | + lower | letter | digit | paren | delim | opchar | + Unicode_Sm | Unicode_So)” printableChar ::= “all characters in [\u0020, \u007F] inclusive” charEscapeSeq ::= ‘\’ (‘b’ | ‘t’ | ‘n’ | ‘f’ | ‘r’ | ‘"’ | ‘'’ | ‘\’) @@ -93,8 +93,8 @@ colonEol ::= ": at end of line that can start a template body" abstract case catch class def do else enum export extends false final finally for given if implicit import lazy match new -null object package private protected override return -super sealed then throw trait true try +null object override package private protected return +sealed super then throw trait true try type val var while with yield : = <- => <: :> # @ =>> ?=>