Skip to content

Commit

Permalink
Add a doc page
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Nov 25, 2024
1 parent ffac28b commit 52392c7
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
90 changes: 90 additions & 0 deletions docs/_docs/reference/experimental/collection-literals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
layout: doc-page
title: "Collection Literals"
redirectFrom: /docs/reference/other-new-features/collection-literals.html
nightlyOf: https://docs.scala-lang.org/scala3/reference/experimental/collection-literals.html
---


Support for collection literals is enabled by the experimental language import
```scala
import scala.language.experimental.collectionLiterals
```
Collection literals are comma-separated sequences of expressions, like these:
```scala
val oneTwoThree = [1, 2, 3]
val anotherLit = [math.Pi, math.cos(2.0), math.E * 3.0]
val diag = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
val empty = []
val mapy = [1 -> "one", 2 -> "two", 3 -> "three"]
```
The type of a collection literal depends on the expected type. If there is no expected type (as in the examples above) a collection literal is of type `Seq`, except if it consists exclusively elements of the form `a -> b`, then it is of type `Map`. For instance, the literals above would
get inferred types as follows.
```scala
val oneTwoThree: Seq[Int] = [1, 2, 3]
val anotherLit: Seq[Double] = [math.Pi, math.cos(2.0), math.E * 3.0]
val diag: Seq[Seq[Int]] = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
val empty: Seq[Nothing] = []
val mapy: Map[Int, String] = [1 -> "one", 2 -> "two", 3 -> "three"]
```
If there is an expected type `E`, the compiler will search for a given instance of the
type class `ExpressibleAsCollectionLiteral[E]`. This type class is defined in package `scala.compiletime` as follows:
```scala
trait ExpressibleAsCollectionLiteral[+Coll]:

/** The element type of the created collection */
type Elem

/** The inline method that creates the collection */
inline def fromLiteral(inline xs: Elem*): Coll
```
If a best matching instance `ecl` is found, its `fromLiteral` method is used to convert
the elements of the literal to the expected type. If the search is ambiguous, it will be
reported as an error. If no matching instance is found, the literal will be typed by the default scheme as if there was no expected type.

The companion object of `ExpressibleAsCollectionLiteral` contains a number of given instances for standard collection types. For instance, there is:
```scala
given vectorFromLiteral: [T] => ExpressibleAsCollectionLiteral[Vector[T]]:
type Elem = T
inline def fromLiteral(inline xs: T*) = Vector[Elem](xs*)
```
Hence, the definition
```scala
val v: Vector[Int] = [1, 2, 3]
```
would be expanded by the compiler to
```scala
val v: Vector[Int] = vectorFromLiteral.fromLiteral(1, 2, 3)
```
After inlining, this produces
```scala
val v: Vector[Int] = Vector[Int](1, 2, 3)
```
Using this scheme, the literals we have seen earlier could also be given alternative types like these:
```scala
val oneTwoThree: Vector[Int] = [1, 2, 3]
val anotherLit: IArray[Double] = [math.Pi, math.cos(2.0), math.E * 3.0]
val diag: Array[Array[Int]] = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
val empty: ArrayBuffer[Object] = []
val mapy: HashMap[Int, String] = [1 -> "one", 2 -> "two", 3 -> "three"]
```

**Notes**

- Since the fromLiteral method in `ExpressibleAsCollectionLiteral` is an inline method with inline arguments, given instances can implement it as a macro.

- The precise meaning of "is there an expected type?" is as follows: There is no expected
type if the expected type known from the context is _underdefined_ as specified for
implicit search. That is, implicit search for a conversion to the expected type would fail with an error message that contains a note like this:
```
Note that implicit conversions were not tried because the result of an implicit conversion|must be more specific than ...
```
Concretely, this is the case for Wildcard types `?`, `Any`, `AnyRef`, or type variables
bounded by one of these types.

**Syntax**

```
SimpleExpr ::= ...
| ‘[’ ExprInParens {‘,’ ExprInParens} ‘]’
```
1 change: 1 addition & 0 deletions docs/sidebar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ subsection:
- page: reference/experimental/typeclasses.md
- page: reference/experimental/runtimeChecked.md
- page: reference/experimental/better-fors.md
- page: reference/experimental/collection-literals.md
- page: reference/syntax.md
- title: Language Versions
index: reference/language-versions/language-versions.md
Expand Down
7 changes: 7 additions & 0 deletions tests/run/seqlits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,10 @@ object SeqLits:
println(mbs)
println(hbs)
println(mbss)


val oneTwoThree: Vector[Int] = [1, 2, 3]
val anotherLit: IArray[Double] = [math.Pi, math.cos(2.0), math.E * 3.0]
val diag: Array[Array[Int]] = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
val empty: ArrayBuffer[Object] = []
val mapy: HashMap[Int, String] = [1 -> "one", 2 -> "two", 3 -> "three"]

0 comments on commit 52392c7

Please sign in to comment.