From 2caf216dcc12c75d2fb5d4a6a234fda959163c27 Mon Sep 17 00:00:00 2001 From: Stephen Layland Date: Sun, 11 Jun 2023 00:35:09 -0700 Subject: [PATCH 1/8] Create separate string-interpolation.md docs (merged from _overviews/core/string-interpolation.md) --- _overviews/core/string-interpolation.md | 262 -------------- _overviews/scala3-book/ca-context-bounds.md | 2 +- .../scala3-book/ca-context-parameters.md | 2 +- .../ca-contextual-abstractions-intro.md | 2 +- .../scala3-book/ca-extension-methods.md | 2 +- _overviews/scala3-book/ca-given-imports.md | 2 +- .../scala3-book/ca-implicit-conversions.md | 2 +- .../scala3-book/ca-multiversal-equality.md | 2 +- _overviews/scala3-book/ca-summary.md | 2 +- _overviews/scala3-book/ca-type-classes.md | 2 +- _overviews/scala3-book/collections-classes.md | 2 +- _overviews/scala3-book/collections-intro.md | 2 +- _overviews/scala3-book/collections-methods.md | 2 +- _overviews/scala3-book/collections-summary.md | 2 +- _overviews/scala3-book/concurrency.md | 2 +- _overviews/scala3-book/control-structures.md | 2 +- _overviews/scala3-book/domain-modeling-fp.md | 2 +- .../scala3-book/domain-modeling-intro.md | 2 +- _overviews/scala3-book/domain-modeling-oop.md | 2 +- .../scala3-book/domain-modeling-tools.md | 2 +- _overviews/scala3-book/first-look-at-types.md | 122 ++----- .../fp-functional-error-handling.md | 2 +- .../scala3-book/fp-functions-are-values.md | 2 +- _overviews/scala3-book/fp-immutable-values.md | 2 +- _overviews/scala3-book/fp-intro.md | 2 +- _overviews/scala3-book/fp-pure-functions.md | 2 +- _overviews/scala3-book/fp-summary.md | 2 +- _overviews/scala3-book/fp-what-is-fp.md | 2 +- .../scala3-book/fun-anonymous-functions.md | 2 +- _overviews/scala3-book/fun-eta-expansion.md | 2 +- .../scala3-book/fun-function-variables.md | 2 +- _overviews/scala3-book/fun-hofs.md | 2 +- _overviews/scala3-book/fun-intro.md | 2 +- _overviews/scala3-book/fun-summary.md | 2 +- .../scala3-book/fun-write-map-function.md | 2 +- .../fun-write-method-returns-function.md | 2 +- .../scala3-book/interacting-with-java.md | 2 +- _overviews/scala3-book/methods-intro.md | 2 +- .../scala3-book/methods-main-methods.md | 2 +- _overviews/scala3-book/methods-most.md | 2 +- _overviews/scala3-book/methods-summary.md | 2 +- _overviews/scala3-book/packaging-imports.md | 2 +- _overviews/scala3-book/scala-for-java-devs.md | 2 +- .../scala3-book/scala-for-javascript-devs.md | 2 +- .../scala3-book/scala-for-python-devs.md | 2 +- _overviews/scala3-book/scala-tools.md | 2 +- .../scala3-book/string-interpolation.md | 339 ++++++++++++++++++ _overviews/scala3-book/tools-sbt.md | 2 +- _overviews/scala3-book/tools-worksheets.md | 2 +- _overviews/scala3-book/types-adts-gadts.md | 2 +- .../scala3-book/types-dependent-function.md | 2 +- _overviews/scala3-book/types-generics.md | 2 +- _overviews/scala3-book/types-inferred.md | 2 +- _overviews/scala3-book/types-intersection.md | 2 +- _overviews/scala3-book/types-introduction.md | 2 +- _overviews/scala3-book/types-opaque-types.md | 2 +- _overviews/scala3-book/types-others.md | 2 +- _overviews/scala3-book/types-structural.md | 2 +- _overviews/scala3-book/types-union.md | 2 +- _overviews/scala3-book/types-variance.md | 2 +- _overviews/scala3-book/where-next.md | 2 +- 61 files changed, 433 insertions(+), 406 deletions(-) delete mode 100644 _overviews/core/string-interpolation.md create mode 100644 _overviews/scala3-book/string-interpolation.md diff --git a/_overviews/core/string-interpolation.md b/_overviews/core/string-interpolation.md deleted file mode 100644 index e2ad7b2366..0000000000 --- a/_overviews/core/string-interpolation.md +++ /dev/null @@ -1,262 +0,0 @@ ---- -layout: singlepage-overview -title: String Interpolation -partof: string-interpolation - -languages: [es, ja, zh-cn] - -permalink: /overviews/core/:title.html ---- - -**Josh Suereth** - -## Introduction - -Starting in Scala 2.10.0, Scala offers a new mechanism to create strings from your data: String Interpolation. -String Interpolation allows users to embed variable references directly in *processed* string literals. Here's an example: - -{% tabs example-1 %} -{% tab 'Scala 2 and 3' for=example-1 %} - val name = "James" - println(s"Hello, $name") // Hello, James -{% endtab %} -{% endtabs %} - -In the above, the literal `s"Hello, $name"` is a *processed* string literal. This means that the compiler does some additional -work to this literal. A processed string literal is denoted by a set of characters preceding the `"`. String interpolation -was introduced by [SIP-11](https://docs.scala-lang.org/sips/pending/string-interpolation.html), which contains all details of the implementation. - -## Usage - -Scala provides three string interpolation methods out of the box: `s`, `f` and `raw`. - -### The `s` String Interpolator - -Prepending `s` to any string literal allows the usage of variables directly in the string. You've already seen an example here: - -{% tabs example-2 %} -{% tab 'Scala 2 and 3' for=example-2 %} - val name = "James" - println(s"Hello, $name") // Hello, James -{% endtab %} -{% endtabs %} - -Here `$name` is nested inside an `s` processed string. The `s` interpolator knows to insert the value of the `name` variable at this location -in the string, resulting in the string `Hello, James`. With the `s` interpolator, any name that is in scope can be used within a string. - -String interpolators can also take arbitrary expressions. For example: - -{% tabs example-3 %} -{% tab 'Scala 2 and 3' for=example-3 %} - println(s"1 + 1 = ${1 + 1}") -{% endtab %} -{% endtabs %} - -will print the string `1 + 1 = 2`. Any arbitrary expression can be embedded in `${}`. - -For some special characters, it is necessary to escape them when embedded within a string. -To represent an actual dollar sign you can double it `$$`, like here: - -{% tabs example-4 %} -{% tab 'Scala 2 and 3' for=example-4 %} - println(s"New offers starting at $$14.99") -{% endtab %} -{% endtabs %} - -which will print the string `New offers starting at $14.99`. - -Double quotes also need to be escaped. This can be done by using triple quotes as shown: - -{% tabs example-5 %} -{% tab 'Scala 2 and 3' for=example-5 %} - val person = """{"name":"James"}""" -{% endtab %} -{% endtabs %} - -which will produce the string `{"name":"James"}` when printed. - -### The `f` Interpolator - -Prepending `f` to any string literal allows the creation of simple formatted strings, similar to `printf` in other languages. When using the `f` -interpolator, all variable references should be followed by a `printf`-style format string, like `%d`. Let's look at an example: - -{% tabs example-6 %} -{% tab 'Scala 2 and 3' for=example-6 %} - val height = 1.9d - val name = "James" - println(f"$name%s is $height%2.2f meters tall") // James is 1.90 meters tall -{% endtab %} -{% endtabs %} - -The `f` interpolator is typesafe. If you try to pass a format string that only works for integers but pass a double, the compiler will issue an -error. For example: - -{% tabs f-interpolator-error class=tabs-scala-version %} - -{% tab 'Scala 2' for=f-interpolator-error %} -```scala -val height: Double = 1.9d - -scala> f"$height%4d" -:9: error: type mismatch; - found : Double - required: Int - f"$height%4d" - ^ -``` -{% endtab %} - -{% tab 'Scala 3' for=f-interpolator-error %} -```scala -val height: Double = 1.9d - -scala> f"$height%4d" --- Error: ---------------------------------------------------------------------- -1 |f"$height%4d" - | ^^^^^^ - | Found: (height : Double), Required: Int, Long, Byte, Short, BigInt -1 error found - -``` -{% endtab %} - -{% endtabs %} - -The `f` interpolator makes use of the string format utilities available from Java. The formats allowed after the `%` character are outlined in the -[Formatter javadoc](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Formatter.html#detail). If there is no `%` character after a variable -definition a formatter of `%s` (`String`) is assumed. - -### The `raw` Interpolator - -The raw interpolator is similar to the `s` interpolator except that it performs no escaping of literals within the string. Here's an example processed string: - -{% tabs example-7 %} -{% tab 'Scala 2 and 3' for=example-7 %} - scala> s"a\nb" - res0: String = - a - b -{% endtab %} -{% endtabs %} - -Here the `s` string interpolator replaced the characters `\n` with a return character. The `raw` interpolator will not do that. - -{% tabs example-8 %} -{% tab 'Scala 2 and 3' for=example-8 %} - scala> raw"a\nb" - res1: String = a\nb -{% endtab %} -{% endtabs %} - -The raw interpolator is useful when you want to avoid having expressions like `\n` turn into a return character. - -In addition to the three default string interpolators, users can define their own. - -## Advanced Usage - -In Scala, all processed string literals are simple code transformations. Anytime the compiler encounters a string literal of the form: - -{% tabs example-9 %} -{% tab 'Scala 2 and 3' for=example-9 %} - id"string content" -{% endtab %} -{% endtabs %} - -it transforms it into a method call (`id`) on an instance of [StringContext](https://www.scala-lang.org/api/current/scala/StringContext.html). -This method can also be available on implicit scope. -To define our own string interpolation, we need to create an implicit class (Scala 2) or an `extension` method (Scala 3) that adds a new method to `StringContext`. -Here's an example: - -{% tabs json-definition-and-usage class=tabs-scala-version %} - -{% tab 'Scala 2' for=json-definition-and-usage %} -```scala -// Note: We extends AnyVal to prevent runtime instantiation. See -// value class guide for more info. -implicit class JsonHelper(val sc: StringContext) extends AnyVal { - def json(args: Any*): JSONObject = sys.error("TODO - IMPLEMENT") -} - -def giveMeSomeJson(x: JSONObject): Unit = ... - -giveMeSomeJson(json"{ name: $name, id: $id }") -``` -{% endtab %} - -{% tab 'Scala 3' for=json-definition-and-usage %} -```scala -extension (sc: StringContext) - def json(args: Any*): JSONObject = sys.error("TODO - IMPLEMENT") - -def giveMeSomeJson(x: JSONObject): Unit = ... - -giveMeSomeJson(json"{ name: $name, id: $id }") -``` -{% endtab %} - -{% endtabs %} - -In this example, we're attempting to create a JSON literal syntax using string interpolation. The `JsonHelper` implicit class must be in scope to use this syntax, and the json method would need a complete implementation. However, the result of such a formatted string literal would not be a string, but a `JSONObject`. - -When the compiler encounters the literal `json"{ name: $name, id: $id }"` it rewrites it to the following expression: - -{% tabs extension-desugaring class=tabs-scala-version %} - -{% tab 'Scala 2' for=extension-desugaring %} -```scala -new StringContext("{ name: ", ", id: ", " }").json(name, id) -``` - -The implicit class is then used to rewrite it to the following: - -```scala -new JsonHelper(new StringContext("{ name: ", ", id: ", " }")).json(name, id) -``` -{% endtab %} - -{% tab 'Scala 3' for=extension-desugaring %} -```scala -StringContext("{ name: ", ", id: ", " }").json(name, id) -``` -{% endtab %} - -{% endtabs %} - -So, the `json` method has access to the raw pieces of strings and each expression as a value. A simplified (buggy) implementation of this method could be: - -{% tabs json-fake-implementation class=tabs-scala-version %} - -{% tab 'Scala 2' for=json-fake-implementation %} -```scala -implicit class JsonHelper(val sc: StringContext) extends AnyVal { - def json(args: Any*): JSONObject = { - val strings = sc.parts.iterator - val expressions = args.iterator - val buf = new StringBuilder(strings.next()) - while (strings.hasNext) { - buf.append(expressions.next()) - buf.append(strings.next()) - } - parseJson(buf) - } -} -``` -{% endtab %} - -{% tab 'Scala 3' for=json-fake-implementation %} -```scala -extension (sc: StringContext) - def json(args: Any*): JSONObject = - val strings = sc.parts.iterator - val expressions = args.iterator - val buf = new StringBuilder(strings.next()) - while strings.hasNext do - buf.append(expressions.next()) - buf.append(strings.next()) - parseJson(buf) -``` -{% endtab %} - -{% endtabs %} - -Each of the string portions of the processed string are exposed in the `StringContext`'s `parts` member. Each of the expression values is passed into the `json` method's `args` parameter. The `json` method takes this and generates a big string which it then parses into JSON. A more sophisticated implementation could avoid having to generate this string and simply construct the JSON directly from the raw strings and expression values. diff --git a/_overviews/scala3-book/ca-context-bounds.md b/_overviews/scala3-book/ca-context-bounds.md index fee7cbd146..efafda98d8 100644 --- a/_overviews/scala3-book/ca-context-bounds.md +++ b/_overviews/scala3-book/ca-context-bounds.md @@ -3,7 +3,7 @@ title: Context Bounds type: section description: This page demonstrates Context Bounds in Scala. languages: [zh-cn] -num: 61 +num: 62 previous-page: ca-context-parameters next-page: ca-given-imports --- diff --git a/_overviews/scala3-book/ca-context-parameters.md b/_overviews/scala3-book/ca-context-parameters.md index 81ca5f7023..5ae6c43b39 100644 --- a/_overviews/scala3-book/ca-context-parameters.md +++ b/_overviews/scala3-book/ca-context-parameters.md @@ -3,7 +3,7 @@ title: Context Parameters type: section description: This page demonstrates how to declare context parameters, and how the compiler infers them at call-site. languages: [zh-cn] -num: 60 +num: 61 previous-page: ca-extension-methods next-page: ca-context-bounds redirect_from: /scala3/book/ca-given-using-clauses.html diff --git a/_overviews/scala3-book/ca-contextual-abstractions-intro.md b/_overviews/scala3-book/ca-contextual-abstractions-intro.md index 5b703e5e6f..33c10dd6cb 100644 --- a/_overviews/scala3-book/ca-contextual-abstractions-intro.md +++ b/_overviews/scala3-book/ca-contextual-abstractions-intro.md @@ -3,7 +3,7 @@ title: Contextual Abstractions type: chapter description: This chapter provides an introduction to the Scala 3 concept of Contextual Abstractions. languages: [zh-cn] -num: 58 +num: 59 previous-page: types-others next-page: ca-extension-methods --- diff --git a/_overviews/scala3-book/ca-extension-methods.md b/_overviews/scala3-book/ca-extension-methods.md index 4b9cf2ef24..65b30183f4 100644 --- a/_overviews/scala3-book/ca-extension-methods.md +++ b/_overviews/scala3-book/ca-extension-methods.md @@ -3,7 +3,7 @@ title: Extension Methods type: section description: This page demonstrates how Extension Methods work in Scala 3. languages: [zh-cn] -num: 59 +num: 60 previous-page: ca-contextual-abstractions-intro next-page: ca-context-parameters scala3: true diff --git a/_overviews/scala3-book/ca-given-imports.md b/_overviews/scala3-book/ca-given-imports.md index 37a5a9e626..399ff6add0 100644 --- a/_overviews/scala3-book/ca-given-imports.md +++ b/_overviews/scala3-book/ca-given-imports.md @@ -3,7 +3,7 @@ title: Given Imports type: section description: This page demonstrates how 'given' import statements work in Scala 3. languages: [zh-cn] -num: 62 +num: 63 previous-page: ca-context-bounds next-page: ca-type-classes scala3: true diff --git a/_overviews/scala3-book/ca-implicit-conversions.md b/_overviews/scala3-book/ca-implicit-conversions.md index 2318323b95..16e9dec53a 100644 --- a/_overviews/scala3-book/ca-implicit-conversions.md +++ b/_overviews/scala3-book/ca-implicit-conversions.md @@ -3,7 +3,7 @@ title: Implicit Conversions type: section description: This page demonstrates how to implement Implicit Conversions in Scala. languages: [zh-cn] -num: 65 +num: 66 previous-page: ca-multiversal-equality next-page: ca-summary --- diff --git a/_overviews/scala3-book/ca-multiversal-equality.md b/_overviews/scala3-book/ca-multiversal-equality.md index 2e3308d25b..be63a600a3 100644 --- a/_overviews/scala3-book/ca-multiversal-equality.md +++ b/_overviews/scala3-book/ca-multiversal-equality.md @@ -3,7 +3,7 @@ title: Multiversal Equality type: section description: This page demonstrates how to implement Multiversal Equality in Scala 3. languages: [zh-cn] -num: 64 +num: 65 previous-page: ca-type-classes next-page: ca-implicit-conversions scala3: true diff --git a/_overviews/scala3-book/ca-summary.md b/_overviews/scala3-book/ca-summary.md index e3f3da3cad..2a9d281211 100644 --- a/_overviews/scala3-book/ca-summary.md +++ b/_overviews/scala3-book/ca-summary.md @@ -3,7 +3,7 @@ title: Summary type: section description: This page provides a summary of the Contextual Abstractions lessons. languages: [zh-cn] -num: 66 +num: 67 previous-page: ca-implicit-conversions next-page: concurrency --- diff --git a/_overviews/scala3-book/ca-type-classes.md b/_overviews/scala3-book/ca-type-classes.md index d79680a8be..36ae7634cf 100644 --- a/_overviews/scala3-book/ca-type-classes.md +++ b/_overviews/scala3-book/ca-type-classes.md @@ -3,7 +3,7 @@ title: Type Classes type: section description: This page demonstrates how to create and use type classes. languages: [zh-cn] -num: 63 +num: 64 previous-page: ca-given-imports next-page: ca-multiversal-equality redirect_from: /scala3/book/types-type-classes.html diff --git a/_overviews/scala3-book/collections-classes.md b/_overviews/scala3-book/collections-classes.md index c68bc9e035..8a91c05076 100644 --- a/_overviews/scala3-book/collections-classes.md +++ b/_overviews/scala3-book/collections-classes.md @@ -3,7 +3,7 @@ title: Collections Types type: section description: This page introduces the common Scala 3 collections types and some of their methods. languages: [ru, zh-cn] -num: 37 +num: 38 previous-page: collections-intro next-page: collections-methods --- diff --git a/_overviews/scala3-book/collections-intro.md b/_overviews/scala3-book/collections-intro.md index befedef0e6..9d99900c07 100644 --- a/_overviews/scala3-book/collections-intro.md +++ b/_overviews/scala3-book/collections-intro.md @@ -3,7 +3,7 @@ title: Scala Collections type: chapter description: This page provides and introduction to the common collections classes and their methods in Scala 3. languages: [ru, zh-cn] -num: 36 +num: 37 previous-page: packaging-imports next-page: collections-classes --- diff --git a/_overviews/scala3-book/collections-methods.md b/_overviews/scala3-book/collections-methods.md index f165a2c0e9..c805aac639 100644 --- a/_overviews/scala3-book/collections-methods.md +++ b/_overviews/scala3-book/collections-methods.md @@ -3,7 +3,7 @@ title: Collections Methods type: section description: This page demonstrates the common methods on the Scala 3 collections classes. languages: [ru, zh-cn] -num: 38 +num: 39 previous-page: collections-classes next-page: collections-summary --- diff --git a/_overviews/scala3-book/collections-summary.md b/_overviews/scala3-book/collections-summary.md index c8ac5512fa..0112990df4 100644 --- a/_overviews/scala3-book/collections-summary.md +++ b/_overviews/scala3-book/collections-summary.md @@ -3,7 +3,7 @@ title: Summary type: section description: This page provides a summary of the Collections chapter. languages: [ru, zh-cn] -num: 39 +num: 40 previous-page: collections-methods next-page: fp-intro --- diff --git a/_overviews/scala3-book/concurrency.md b/_overviews/scala3-book/concurrency.md index ff2151bd4b..173e0ff72a 100644 --- a/_overviews/scala3-book/concurrency.md +++ b/_overviews/scala3-book/concurrency.md @@ -3,7 +3,7 @@ title: Concurrency type: chapter description: This page discusses how Scala concurrency works, with an emphasis on Scala Futures. languages: [zh-cn] -num: 67 +num: 68 previous-page: ca-summary next-page: scala-tools --- diff --git a/_overviews/scala3-book/control-structures.md b/_overviews/scala3-book/control-structures.md index 198a4955d2..2b86698980 100644 --- a/_overviews/scala3-book/control-structures.md +++ b/_overviews/scala3-book/control-structures.md @@ -3,7 +3,7 @@ title: Control Structures type: chapter description: This page provides an introduction to Scala's control structures, including if/then/else, 'for' loops, 'for' expressions, 'match' expressions, try/catch/finally, and 'while' loops. languages: [ru, zh-cn] -num: 18 +num: 19 previous-page: first-look-at-types next-page: domain-modeling-intro --- diff --git a/_overviews/scala3-book/domain-modeling-fp.md b/_overviews/scala3-book/domain-modeling-fp.md index f8ab2fb571..ce72aca425 100644 --- a/_overviews/scala3-book/domain-modeling-fp.md +++ b/_overviews/scala3-book/domain-modeling-fp.md @@ -3,7 +3,7 @@ title: FP Modeling type: section description: This chapter provides an introduction to FP domain modeling with Scala 3. languages: [ru, zh-cn] -num: 22 +num: 23 previous-page: domain-modeling-oop next-page: methods-intro --- diff --git a/_overviews/scala3-book/domain-modeling-intro.md b/_overviews/scala3-book/domain-modeling-intro.md index 578cf001df..fada05d5f3 100644 --- a/_overviews/scala3-book/domain-modeling-intro.md +++ b/_overviews/scala3-book/domain-modeling-intro.md @@ -3,7 +3,7 @@ title: Domain Modeling type: chapter description: This chapter provides an introduction to domain modeling in Scala 3. languages: [ru, zh-cn] -num: 19 +num: 20 previous-page: control-structures next-page: domain-modeling-tools --- diff --git a/_overviews/scala3-book/domain-modeling-oop.md b/_overviews/scala3-book/domain-modeling-oop.md index 8a55131a20..948504139e 100644 --- a/_overviews/scala3-book/domain-modeling-oop.md +++ b/_overviews/scala3-book/domain-modeling-oop.md @@ -3,7 +3,7 @@ title: OOP Modeling type: section description: This chapter provides an introduction to OOP domain modeling with Scala 3. languages: [ru, zh-cn] -num: 21 +num: 22 previous-page: domain-modeling-tools next-page: domain-modeling-fp --- diff --git a/_overviews/scala3-book/domain-modeling-tools.md b/_overviews/scala3-book/domain-modeling-tools.md index df1a7a6fc8..9b6901504f 100644 --- a/_overviews/scala3-book/domain-modeling-tools.md +++ b/_overviews/scala3-book/domain-modeling-tools.md @@ -3,7 +3,7 @@ title: Tools type: section description: This chapter provides an introduction to the available domain modeling tools in Scala 3, including classes, traits, enums, and more. languages: [ru, zh-cn] -num: 20 +num: 21 previous-page: domain-modeling-intro next-page: domain-modeling-oop --- diff --git a/_overviews/scala3-book/first-look-at-types.md b/_overviews/scala3-book/first-look-at-types.md index 1a795c8922..5cdb32e57f 100644 --- a/_overviews/scala3-book/first-look-at-types.md +++ b/_overviews/scala3-book/first-look-at-types.md @@ -5,7 +5,7 @@ description: This page provides a brief introduction to Scala's built-in data ty languages: [ru, zh-cn] num: 17 previous-page: taste-summary -next-page: control-structures +next-page: string-interpolation --- @@ -21,8 +21,7 @@ The diagram below illustrates a subset of the type hierarchy. `Any` is the supertype of all types, also called the **top type**. It defines certain universal methods such as `equals`, `hashCode`, and `toString`. -The top-type `Any` has a subtype [`Matchable`][matchable], which is used to mark all types that we can perform pattern matching on. -It is important to guarantee a property call _"parametricity"_. +The top-type `Any` has a subtype [`Matchable`][matchable], which is used to mark all types that we can perform pattern matching on. It is important to guarantee a property call _"parametricity"_. We will not go into details here, but in summary, it means that we cannot pattern match on values of type `Any`, but only on values that are a subtype of `Matchable`. The [reference documentation][matchable] contains more information about `Matchable`. @@ -168,89 +167,10 @@ Those data types and their ranges are: | Char | 16-bit unsigned Unicode character (0 to 2^16-1, inclusive)
0 to 65,535 | | String | a sequence of `Char` | -## `BigInt` and `BigDecimal` - -When you need really large numbers, use the `BigInt` and `BigDecimal` types: - -{% tabs type-bigint %} -{% tab 'Scala 2 and 3' for=type-bigint %} -```scala -val a = BigInt(1_234_567_890_987_654_321L) -val b = BigDecimal(123_456.789) -``` -{% endtab %} -{% endtabs %} - -Where `Double` and `Float` are approximate decimal numbers, `BigDecimal` is used for precise arithmetic, such as when working with currency. - -A great thing about `BigInt` and `BigDecimal` is that they support all the operators you’re used to using with numeric types: - -{% tabs type-bigint2 %} -{% tab 'Scala 2 and 3' for=type-bigint2 %} -```scala -val b = BigInt(1234567890) // scala.math.BigInt = 1234567890 -val c = b + b // scala.math.BigInt = 2469135780 -val d = b * b // scala.math.BigInt = 1524157875019052100 -``` -{% endtab %} -{% endtabs %} - -## Two notes about strings - -Scala strings are similar to Java strings, but they have two great additional features: - -- They support string interpolation -- It’s easy to create multiline strings - -### String interpolation - -String interpolation provides a very readable way to use variables inside strings. -For instance, given these three variables: - -{% tabs string-inside1 %} -{% tab 'Scala 2 and 3' for=string-inside1 %} -```scala -val firstName = "John" -val mi = 'C' -val lastName = "Doe" -``` -{% endtab %} -{% endtabs %} - -You can combine those variables in a string like this: - -{% tabs string-inside2 %} -{% tab 'Scala 2 and 3' for=string-inside2 %} -```scala -println(s"Name: $firstName $mi $lastName") // "Name: John C Doe" -``` -{% endtab %} -{% endtabs %} - -Just precede the string with the letter `s`, and then put a `$` symbol before your variable names inside the string. - -To enclose potentially larger expressions inside a string, put them in curly braces: - -{% tabs string-inside3 %} -{% tab 'Scala 2 and 3' for=string-inside3 %} -```scala -println(s"2 + 2 = ${2 + 2}") // prints "2 + 2 = 4" -val x = -1 -println(s"x.abs = ${x.abs}") // prints "x.abs = 1" -``` -{% endtab %} -{% endtabs %} - -#### Other interpolators +## Strings -The `s` that you place before the string is just one possible interpolator. -If you use an `f` instead of an `s`, you can use `printf`-style formatting syntax in the string. -Furthermore, a string interpolator is a just special method, and it is possible to define your own. -For instance, some database libraries define the very powerful `sql` interpolator. - -### Multiline strings - -Multiline strings are created by including the string inside three double-quotes: +Scala strings are similar to Java strings though unlike Java (at least before Java 15), +it's easy to create multiline strings with triple quotes: {% tabs string-mlines1 %} {% tab 'Scala 2 and 3' for=string-mlines1 %} @@ -298,6 +218,36 @@ programming in a typed setting." {% endtab %} {% endtabs %} +Scala strings also support powerful string interpolation methods, which we'll talk about +in the [next chapter][string-interpolation]. + +## `BigInt` and `BigDecimal` + +When you need really large numbers, use the `BigInt` and `BigDecimal` types: + +{% tabs type-bigint %} +{% tab 'Scala 2 and 3' for=type-bigint %} +```scala +val a = BigInt(1_234_567_890_987_654_321L) +val b = BigDecimal(123_456.789) +``` +{% endtab %} +{% endtabs %} + +Where `Double` and `Float` are approximate decimal numbers, `BigDecimal` is used for precise arithmetic, such as when working with currency. + +A great thing about `BigInt` and `BigDecimal` is that they support all the operators you’re used to using with numeric types: + +{% tabs type-bigint2 %} +{% tab 'Scala 2 and 3' for=type-bigint2 %} +```scala +val b = BigInt(1234567890) // scala.math.BigInt = 1234567890 +val c = b + b // scala.math.BigInt = 2469135780 +val d = b * b // scala.math.BigInt = 1524157875019052100 +``` +{% endtab %} +{% endtabs %} + ## Type casting Value types can be cast in the following way: @@ -347,7 +297,7 @@ Alternatives to `null` are discussed in the [Functional Programming chapter][fp] [reference]: {{ site.scala3ref }}/overview.html [matchable]: {{ site.scala3ref }}/other-new-features/matchable.html -[interpolation]: {% link _overviews/core/string-interpolation.md %} [fp]: {% link _overviews/scala3-book/fp-intro.md %} +[string-interpolation]: {% link _overviews/scala3-book/string-interpolation.md %} [option-api]: https://scala-lang.org/api/3.x/scala/Option.html [safe-null]: {{ site.scala3ref }}/experimental/explicit-nulls.html diff --git a/_overviews/scala3-book/fp-functional-error-handling.md b/_overviews/scala3-book/fp-functional-error-handling.md index 829845eaf8..e22fc2b4bb 100644 --- a/_overviews/scala3-book/fp-functional-error-handling.md +++ b/_overviews/scala3-book/fp-functional-error-handling.md @@ -3,7 +3,7 @@ title: Functional Error Handling type: section description: This section provides an introduction to functional error handling in Scala 3. languages: [ru, zh-cn] -num: 45 +num: 46 previous-page: fp-functions-are-values next-page: fp-summary --- diff --git a/_overviews/scala3-book/fp-functions-are-values.md b/_overviews/scala3-book/fp-functions-are-values.md index 48f7e4ca3a..e656d3c9f9 100644 --- a/_overviews/scala3-book/fp-functions-are-values.md +++ b/_overviews/scala3-book/fp-functions-are-values.md @@ -3,7 +3,7 @@ title: Functions Are Values type: section description: This section looks at the use of functions as values in functional programming. languages: [ru, zh-cn] -num: 44 +num: 45 previous-page: fp-pure-functions next-page: fp-functional-error-handling --- diff --git a/_overviews/scala3-book/fp-immutable-values.md b/_overviews/scala3-book/fp-immutable-values.md index 413d2d0495..2226ceac95 100644 --- a/_overviews/scala3-book/fp-immutable-values.md +++ b/_overviews/scala3-book/fp-immutable-values.md @@ -3,7 +3,7 @@ title: Immutable Values type: section description: This section looks at the use of immutable values in functional programming. languages: [ru, zh-cn] -num: 42 +num: 43 previous-page: fp-what-is-fp next-page: fp-pure-functions --- diff --git a/_overviews/scala3-book/fp-intro.md b/_overviews/scala3-book/fp-intro.md index 7d6e6f4114..d99ec1d0e8 100644 --- a/_overviews/scala3-book/fp-intro.md +++ b/_overviews/scala3-book/fp-intro.md @@ -3,7 +3,7 @@ title: Functional Programming type: chapter description: This chapter provides an introduction to functional programming in Scala 3. languages: [ru, zh-cn] -num: 40 +num: 41 previous-page: collections-summary next-page: fp-what-is-fp --- diff --git a/_overviews/scala3-book/fp-pure-functions.md b/_overviews/scala3-book/fp-pure-functions.md index 754d6f46a5..641eee59ce 100644 --- a/_overviews/scala3-book/fp-pure-functions.md +++ b/_overviews/scala3-book/fp-pure-functions.md @@ -3,7 +3,7 @@ title: Pure Functions type: section description: This section looks at the use of pure functions in functional programming. languages: [ru, zh-cn] -num: 43 +num: 44 previous-page: fp-immutable-values next-page: fp-functions-are-values --- diff --git a/_overviews/scala3-book/fp-summary.md b/_overviews/scala3-book/fp-summary.md index 55233f851c..7695293e9d 100644 --- a/_overviews/scala3-book/fp-summary.md +++ b/_overviews/scala3-book/fp-summary.md @@ -3,7 +3,7 @@ title: Summary type: section description: This section summarizes the previous functional programming sections. languages: [ru, zh-cn] -num: 46 +num: 47 previous-page: fp-functional-error-handling next-page: types-introduction --- diff --git a/_overviews/scala3-book/fp-what-is-fp.md b/_overviews/scala3-book/fp-what-is-fp.md index 1e37279ae0..2eca848e60 100644 --- a/_overviews/scala3-book/fp-what-is-fp.md +++ b/_overviews/scala3-book/fp-what-is-fp.md @@ -3,7 +3,7 @@ title: What is Functional Programming? type: section description: This section provides an answer to the question, what is functional programming? languages: [ru, zh-cn] -num: 41 +num: 42 previous-page: fp-intro next-page: fp-immutable-values --- diff --git a/_overviews/scala3-book/fun-anonymous-functions.md b/_overviews/scala3-book/fun-anonymous-functions.md index faf32eb76d..428186b968 100644 --- a/_overviews/scala3-book/fun-anonymous-functions.md +++ b/_overviews/scala3-book/fun-anonymous-functions.md @@ -3,7 +3,7 @@ title: Anonymous Functions type: section description: This page shows how to use anonymous functions in Scala, including examples with the List class 'map' and 'filter' functions. languages: [ru, zh-cn] -num: 28 +num: 29 previous-page: fun-intro next-page: fun-function-variables --- diff --git a/_overviews/scala3-book/fun-eta-expansion.md b/_overviews/scala3-book/fun-eta-expansion.md index dcfc76acf5..e45f48cc68 100644 --- a/_overviews/scala3-book/fun-eta-expansion.md +++ b/_overviews/scala3-book/fun-eta-expansion.md @@ -3,7 +3,7 @@ title: Eta Expansion type: section description: This page discusses Eta Expansion, the Scala technology that automatically and transparently converts methods into functions. languages: [ru, zh-cn] -num: 30 +num: 31 previous-page: fun-function-variables next-page: fun-hofs --- diff --git a/_overviews/scala3-book/fun-function-variables.md b/_overviews/scala3-book/fun-function-variables.md index 70805a5240..04c612b7b7 100644 --- a/_overviews/scala3-book/fun-function-variables.md +++ b/_overviews/scala3-book/fun-function-variables.md @@ -3,7 +3,7 @@ title: Function Variables type: section description: This page shows how to use function variables in Scala. languages: [ru, zh-cn] -num: 29 +num: 30 previous-page: fun-anonymous-functions next-page: fun-eta-expansion --- diff --git a/_overviews/scala3-book/fun-hofs.md b/_overviews/scala3-book/fun-hofs.md index 45d764dee4..013f47a560 100644 --- a/_overviews/scala3-book/fun-hofs.md +++ b/_overviews/scala3-book/fun-hofs.md @@ -3,7 +3,7 @@ title: Higher-Order Functions type: section description: This page demonstrates how to create and use higher-order functions in Scala. languages: [ru, zh-cn] -num: 31 +num: 32 previous-page: fun-eta-expansion next-page: fun-write-map-function --- diff --git a/_overviews/scala3-book/fun-intro.md b/_overviews/scala3-book/fun-intro.md index aa4345a188..a3c82e51c7 100644 --- a/_overviews/scala3-book/fun-intro.md +++ b/_overviews/scala3-book/fun-intro.md @@ -3,7 +3,7 @@ title: Functions type: chapter description: This chapter looks at all topics related to functions in Scala 3. languages: [ru, zh-cn] -num: 27 +num: 28 previous-page: methods-summary next-page: fun-anonymous-functions --- diff --git a/_overviews/scala3-book/fun-summary.md b/_overviews/scala3-book/fun-summary.md index 99089f5dec..ffd7bb7bd7 100644 --- a/_overviews/scala3-book/fun-summary.md +++ b/_overviews/scala3-book/fun-summary.md @@ -3,7 +3,7 @@ title: Summary type: section description: This page provides a summary of the previous 'Functions' sections. languages: [ru, zh-cn] -num: 34 +num: 35 previous-page: fun-write-method-returns-function next-page: packaging-imports --- diff --git a/_overviews/scala3-book/fun-write-map-function.md b/_overviews/scala3-book/fun-write-map-function.md index c7c9234760..02ee9abf75 100644 --- a/_overviews/scala3-book/fun-write-map-function.md +++ b/_overviews/scala3-book/fun-write-map-function.md @@ -3,7 +3,7 @@ title: Write Your Own map Method type: section description: This page demonstrates how to create and use higher-order functions in Scala. languages: [ru, zh-cn] -num: 32 +num: 33 previous-page: fun-hofs next-page: fun-write-method-returns-function --- diff --git a/_overviews/scala3-book/fun-write-method-returns-function.md b/_overviews/scala3-book/fun-write-method-returns-function.md index 79795089ea..1e6fc8b304 100644 --- a/_overviews/scala3-book/fun-write-method-returns-function.md +++ b/_overviews/scala3-book/fun-write-method-returns-function.md @@ -3,7 +3,7 @@ title: Creating a Method That Returns a Function type: section description: This page demonstrates how to create and use higher-order functions in Scala. languages: [ru, zh-cn] -num: 33 +num: 34 previous-page: fun-write-map-function next-page: fun-summary --- diff --git a/_overviews/scala3-book/interacting-with-java.md b/_overviews/scala3-book/interacting-with-java.md index 18f5667446..06a5a8fa62 100644 --- a/_overviews/scala3-book/interacting-with-java.md +++ b/_overviews/scala3-book/interacting-with-java.md @@ -3,7 +3,7 @@ title: Interacting with Java type: chapter description: This page demonstrates how Scala code can interact with Java, and how Java code can interact with Scala code. languages: [zh-cn] -num: 71 +num: 72 previous-page: tools-worksheets next-page: scala-for-java-devs --- diff --git a/_overviews/scala3-book/methods-intro.md b/_overviews/scala3-book/methods-intro.md index 2bf6be1247..59e91c3c6c 100644 --- a/_overviews/scala3-book/methods-intro.md +++ b/_overviews/scala3-book/methods-intro.md @@ -3,7 +3,7 @@ title: Methods type: chapter description: This section introduces methods in Scala 3. languages: [ru, zh-cn] -num: 23 +num: 24 previous-page: domain-modeling-fp next-page: methods-most --- diff --git a/_overviews/scala3-book/methods-main-methods.md b/_overviews/scala3-book/methods-main-methods.md index 407c124d2c..cc26716f16 100644 --- a/_overviews/scala3-book/methods-main-methods.md +++ b/_overviews/scala3-book/methods-main-methods.md @@ -3,7 +3,7 @@ title: Main Methods in Scala 3 type: section description: This page describes how 'main' methods and the '@main' annotation work in Scala 3. languages: [ru, zh-cn] -num: 25 +num: 26 previous-page: methods-most next-page: methods-summary --- diff --git a/_overviews/scala3-book/methods-most.md b/_overviews/scala3-book/methods-most.md index 1cadaf3ebe..8af9552e6a 100644 --- a/_overviews/scala3-book/methods-most.md +++ b/_overviews/scala3-book/methods-most.md @@ -3,7 +3,7 @@ title: Method Features type: section description: This section introduces Scala 3 methods, including main methods, extension methods, and more. languages: [ru, zh-cn] -num: 24 +num: 25 previous-page: methods-intro next-page: methods-main-methods --- diff --git a/_overviews/scala3-book/methods-summary.md b/_overviews/scala3-book/methods-summary.md index 54abeef761..8d36108654 100644 --- a/_overviews/scala3-book/methods-summary.md +++ b/_overviews/scala3-book/methods-summary.md @@ -3,7 +3,7 @@ title: Summary type: section description: This section summarizes the previous sections on Scala 3 methods. languages: [ru, zh-cn] -num: 26 +num: 27 previous-page: methods-main-methods next-page: fun-intro --- diff --git a/_overviews/scala3-book/packaging-imports.md b/_overviews/scala3-book/packaging-imports.md index 562fc69a46..94126b7f32 100644 --- a/_overviews/scala3-book/packaging-imports.md +++ b/_overviews/scala3-book/packaging-imports.md @@ -3,7 +3,7 @@ title: Packaging and Imports type: chapter description: A discussion of using packages and imports to organize your code, build related modules of code, control scope, and help prevent namespace collisions. languages: [ru, zh-cn] -num: 35 +num: 36 previous-page: fun-summary next-page: collections-intro --- diff --git a/_overviews/scala3-book/scala-for-java-devs.md b/_overviews/scala3-book/scala-for-java-devs.md index 78d86b289b..4a1db9de24 100644 --- a/_overviews/scala3-book/scala-for-java-devs.md +++ b/_overviews/scala3-book/scala-for-java-devs.md @@ -3,7 +3,7 @@ title: Scala for Java Developers type: chapter description: This page is for Java developers who are interested in learning about Scala 3. languages: [zh-cn] -num: 72 +num: 73 previous-page: interacting-with-java next-page: scala-for-javascript-devs --- diff --git a/_overviews/scala3-book/scala-for-javascript-devs.md b/_overviews/scala3-book/scala-for-javascript-devs.md index f2ecd821e4..213b1bada7 100644 --- a/_overviews/scala3-book/scala-for-javascript-devs.md +++ b/_overviews/scala3-book/scala-for-javascript-devs.md @@ -3,7 +3,7 @@ title: Scala for JavaScript Developers type: chapter description: This chapter provides an introduction to Scala 3 for JavaScript developers languages: [zh-cn] -num: 73 +num: 74 previous-page: scala-for-java-devs next-page: scala-for-python-devs --- diff --git a/_overviews/scala3-book/scala-for-python-devs.md b/_overviews/scala3-book/scala-for-python-devs.md index e10b43ebdb..ddaa08584c 100644 --- a/_overviews/scala3-book/scala-for-python-devs.md +++ b/_overviews/scala3-book/scala-for-python-devs.md @@ -3,7 +3,7 @@ title: Scala for Python Developers type: chapter description: This page is for Python developers who are interested in learning about Scala 3. languages: [zh-cn] -num: 74 +num: 75 previous-page: scala-for-javascript-devs next-page: where-next --- diff --git a/_overviews/scala3-book/scala-tools.md b/_overviews/scala3-book/scala-tools.md index 230f7b74ae..1b6badd809 100644 --- a/_overviews/scala3-book/scala-tools.md +++ b/_overviews/scala3-book/scala-tools.md @@ -3,7 +3,7 @@ title: Scala Tools type: chapter description: This chapter looks at two commonly-used Scala tools, sbt and ScalaTest. languages: [zh-cn] -num: 68 +num: 69 previous-page: concurrency next-page: tools-sbt --- diff --git a/_overviews/scala3-book/string-interpolation.md b/_overviews/scala3-book/string-interpolation.md new file mode 100644 index 0000000000..fab59a7dab --- /dev/null +++ b/_overviews/scala3-book/string-interpolation.md @@ -0,0 +1,339 @@ +--- +title: String Interpolation +type: chapter +description: This page provides more information about creating strings and using string +interpolation. +languages: [es, ja, zh-cn] +num: 18 +previous-page: first-look-at-types +next-page: control-structures +--- + +## Introduction + +String interpolation provides a very readable way to use variables inside strings. +For instance: + +{% tabs example-1 %} +{% tab 'Scala 2 and 3' for=example-1 %} +```scala +val name = "John" +val age = 30 +println(s"$name is $age years old") // "John is 30 years old" +``` +{% endtab %} +{% endtabs %} + +Using string interpolation is as simple as putting an `s` in front of your string +quotes, and prefixing any variable names with a `$` symbol. + +### Other interpolators + +The `s` that you place before the string is just one possible interpolator that Scala +provides. + +Scala provides three string interpolation methods out of the box: `s`, `f` and `raw`. +Further, a string interpolator is a just special method so it is possible to define your +own. For instance, some database libraries define the very powerful `sql` interpolator +which returns the result of a database query. + +## The `s` Interpolator (`s`-Strings) + +Prepending `s` to any string literal allows the usage of variables directly in the string. You've already seen an example here: + +{% tabs example-2 %} +{% tab 'Scala 2 and 3' for=example-2 %} +```scala +val name = "John" +val age = 30 +println(s"$name is $age years old") // "John is 30 years old" +``` +{% endtab %} +{% endtabs %} + +Here, the `$name` and `$age` placeholders in the string are replaced by the results of +calling `name.toString` and `age.toString`, respectively. The `s`-String will have +access to all variables that are currently in scope. + +While it may seem obvious, it's important to note here that string interpolation will _not_ happen in normal string literals: + +{% tabs example-3 %} +{% tab 'Scala 2 and 3' for=example-3 %} +```scala +val name = "John" +val age = 30 +println("$name is $age years old") // "$name is $age years old" +``` +{% endtab %} +{% endtabs %} + +String interpolators can also take arbitrary expressions. For example: + +{% tabs example-4 %} +{% tab 'Scala 2 and 3' for=example-4 %} +```scala +println(s"2 + 2 = ${2 + 2}") // prints "2 + 2 = 4" +val x = -1 +println(s"x.abs = ${x.abs}") // prints "x.abs = 1" +``` +{% endtab %} +{% endtabs %} + +Any arbitrary expression can be embedded in `${}`. + +For some special characters, it is necessary to escape them when embedded within a string. +To represent an actual dollar sign you can double it `$$`, like here: + +{% tabs example-5 %} +{% tab 'Scala 2 and 3' for=example-5 %} +```scala +println(s"New offers starting at $$14.99") // prints "New offers starting at $14.99" +``` +{% endtab %} +{% endtabs %} + +Double quotes also need to be escaped. This can be done by using triple quotes as shown: + +{% tabs example-6 %} +{% tab 'Scala 2 and 3' for=example-6 %} +```scala +val person = """{"name":"James"}""" +``` +{% endtab %} +{% endtabs %} + +which will produce the string `{"name":"James"}` when printed. + +## The `f` Interpolator (`f`-Strings) + +Prepending `f` to any string literal allows the creation of simple formatted strings, similar to `printf` in other languages. When using the `f` +interpolator, all variable references should be followed by a `printf`-style format string, like `%d`. Let's look at an example: + +{% tabs example-7 %} +{% tab 'Scala 2 and 3' for=example-7 %} +```scala +val height = 1.9d +val name = "James" +println(f"$name%s is $height%2.2f meters tall") // James is 1.90 meters tall +``` +{% endtab %} +{% endtabs %} + +The `f` interpolator is typesafe. If you try to pass a format string that only works for integers but pass a double, the compiler will issue an +error. For example: + +{% tabs f-interpolator-error class=tabs-scala-version %} + +{% tab 'Scala 2' for=f-interpolator-error %} +```scala +val height: Double = 1.9d + +scala> f"$height%4d" +:9: error: type mismatch; + found : Double + required: Int + f"$height%4d" + ^ +``` +{% endtab %} + +{% tab 'Scala 3' for=f-interpolator-error %} +```scala +val height: Double = 1.9d + +scala> f"$height%4d" +-- Error: ---------------------------------------------------------------------- +1 |f"$height%4d" + | ^^^^^^ + | Found: (height : Double), Required: Int, Long, Byte, Short, BigInt +1 error found + +``` +{% endtab %} +{% endtabs %} + +The `f` interpolator makes use of the string format utilities available from Java. The formats allowed after the `%` character are outlined in the +[Formatter javadoc][java-format-docs]. If there is no `%` character after a variable +definition a formatter of `%s` (`String`) is assumed. + +Finally, as in Java, use `%%` to get a literal `%` character in the output string: + +{% tabs literal-percent %} +{% tab 'Scala 3' for=literal-percent %} +```scala +println(f"3/19 is ${300.0/19}%0.2f%%") // Prints "3/19 is 15.79%" +``` +{% endtab %} +{% endtabs %} + +### The `raw` Interpolator + +The raw interpolator is similar to the `s` interpolator except that it performs no escaping of literals within the string. Here's an example processed string: + +{% tabs example-8 %} +{% tab 'Scala 2 and 3' for=example-8 %} +```scala +scala> s"a\nb" +res0: String = +a +b +``` +{% endtab %} +{% endtabs %} + +Here the `s` string interpolator replaced the characters `\n` with a return character. The `raw` interpolator will not do that. + +{% tabs example-9 %} +{% tab 'Scala 2 and 3' for=example-9 %} +```scala +scala> raw"a\nb" +res1: String = a\nb +``` +{% endtab %} +{% endtabs %} + +The raw interpolator is useful when you want to avoid having expressions like `\n` turn into a return character. + +In addition to the three default string interpolators, users can define their own. + +## Advanced Usage + +The literal `s"Hi $name"` is parsed by scala as a _processed_ string literal. +This means that the compiler does some additional work to this literal. The specifics +of processed strings and string interpolation are described in [SIP-11][sip-11], but +here's a quick example to help illustrate how they work. + +### Custom Interpolators + +In Scala, all processed string literals are simple code transformations. Anytime the compiler encounters a processed string literal of the form: + +{% tabs example-10 %} +{% tab 'Scala 2 and 3' for=example-10 %} +```scala +id"string content" +``` +{% endtab %} +{% endtabs %} + +it transforms it into a method call (`id`) on an instance of [StringContext](https://www.scala-lang.org/api/current/scala/StringContext.html). +This method can also be available on implicit scope. +To define our own string interpolation, we need to create an implicit class (Scala 2) or an `extension` method (Scala 3) that adds a new method to `StringContext`. + +As a trivial example, let's assume we have a simple `Point` class and want to create a custom interpolator that turns `p"a,b"` into a `Point` object. + +{% tabs custom-interpolator-1 %} +{% tab 'Scala 2 and 3' for=custom-interpolator-1 %} +```scala +case class Point(x:Double, y:Double) + +val pt = p"1,-2" // Point(1.0,-2.0) +``` +{% endtab %} +{% endtabs %} + +We'd create a custom `p`-interpolator by first implementing a `StringContext` extension +with something like: + +{% tabs custom-interpolator class=tabs-scala-version %} + +{% tab 'Scala 2' for=custom-interpolator-2 %} +```scala +// Note: We extend AnyVal to prevent runtime instantiation. See +// value class guide for more info. +implicit class PointHelper(val sc: StringContext) extends AnyVal { + def p(args: Any*): Point = ??? +} + +val pt = p"1,-2" // Point(1.0, -2.0) +``` +{% endtab %} + +{% tab 'Scala 3' for=custom-interpolator-2 %} +```scala +extension (sc: StringContext) + def p(args: Any*): Point = ??? + +val pt = p"1,-2" // Point(1.0, -2.0) +``` +{% endtab %} + +{% endtabs %} + +Once this extension is in scope and the Scala compiler encounters `p"some string"`, it +will process `some $string` to turn it into String tokens and expression arguments. +For example, `p"1, $var"` would turn into: + +{% tabs extension-desugaring class=tabs-scala-version %} + +{% tab 'Scala 2' for=extension-desugaring %} +```scala +new StringContext("1, ", "").p(var) +``` + +The implicit class is then used to rewrite it to the following: + +```scala +new PointHelper(new StringContext("1, ", "")).p(var) +``` +{% endtab %} + +{% tab 'Scala 3' for=extension-desugaring %} +```scala +StringContext("1, ","").p(var) +``` +{% endtab %} + +{% endtabs %} + +As a result, each of the fragments of the processed String are exposed in the +`StringContext.parts` member, while any expressions values in the string are passed in +to the method's `args` parameter. + +A naive implementation of our Point interpolator method might look something like below, +though a more sophisticated method may choose to have more precise control over the +processing of the string `parts` and expression `args` instead of reusing the +`s`-Interpolator. + +{% tabs naive-implementation class=tabs-scala-version %} + +{% tab 'Scala 2' for=naive-implementation %} +```scala +implicit class PointHelper(val sc:StringContext) extends AnyVal { + def p(args: Double*): Point = { + // reuse the `s` method and then split on ',' + val pts = sc.s(args:_*).split(",", 2).map { _.toDoubleOption.getOrElse(0.0) } + Point(pts(0), pts(1)) + } +} + +val x=12.0 + +p"1, -2" // Point(1.0, -2.0) +p"${x/5}, $x" // Point(2.4, 12.0) +``` +{% endtab %} + +{% tab 'Scala 3' for=naive-implementation %} +```scala +extension (sc: StringContext) + def p(args: Double*): Point = { + // reuse the `s` method and then split on ',' + val pts = sc.s(args:_*).split(",", 2).map { _.toDoubleOption.getOrElse(0.0) } + Point(pts(0), pts(1)) + } + +val x=12.0 + +p"1, -2" // Point(1.0, -2.0) +p"${x/5}, $x" // Point(2.4, 12.0) +``` +{% endtab %} +{% endtabs %} + +While string interpolators were originally used to create some form of a String, the use +of custom interpolators as above can allow for powerful syntactic shorthand, and the +community has already made swift use of this syntax for things like ansi terminal color +expansion, executing sql queries, magic `$"identifier"` representations, and many others. + +[java-format-docs][https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Formatter.html#detail] +[sip-11]: {% link _sips/sips/string-interpolation.md %} diff --git a/_overviews/scala3-book/tools-sbt.md b/_overviews/scala3-book/tools-sbt.md index 6fd9897a29..8735cbce68 100644 --- a/_overviews/scala3-book/tools-sbt.md +++ b/_overviews/scala3-book/tools-sbt.md @@ -3,7 +3,7 @@ title: Building and Testing Scala Projects with sbt type: section description: This section looks at a commonly-used build tool, sbt, and a testing library, ScalaTest. languages: [zh-cn] -num: 69 +num: 70 previous-page: scala-tools next-page: tools-worksheets --- diff --git a/_overviews/scala3-book/tools-worksheets.md b/_overviews/scala3-book/tools-worksheets.md index 92f7fd66ca..5c8dacf3e5 100644 --- a/_overviews/scala3-book/tools-worksheets.md +++ b/_overviews/scala3-book/tools-worksheets.md @@ -3,7 +3,7 @@ title: Worksheets type: section description: This section looks at worksheets, an alternative to Scala projects. languages: [zh-cn] -num: 70 +num: 71 previous-page: tools-sbt next-page: interacting-with-java --- diff --git a/_overviews/scala3-book/types-adts-gadts.md b/_overviews/scala3-book/types-adts-gadts.md index 5cb2d0e550..a4f31e0040 100644 --- a/_overviews/scala3-book/types-adts-gadts.md +++ b/_overviews/scala3-book/types-adts-gadts.md @@ -3,7 +3,7 @@ title: Algebraic Data Types type: section description: This section introduces and demonstrates algebraic data types (ADTs) in Scala 3. languages: [zh-cn] -num: 52 +num: 53 previous-page: types-union next-page: types-variance scala3: true diff --git a/_overviews/scala3-book/types-dependent-function.md b/_overviews/scala3-book/types-dependent-function.md index 1350477fcd..5a74b28dd0 100644 --- a/_overviews/scala3-book/types-dependent-function.md +++ b/_overviews/scala3-book/types-dependent-function.md @@ -3,7 +3,7 @@ title: Dependent Function Types type: section description: This section introduces and demonstrates dependent function types in Scala 3. languages: [zh-cn] -num: 56 +num: 57 previous-page: types-structural next-page: types-others --- diff --git a/_overviews/scala3-book/types-generics.md b/_overviews/scala3-book/types-generics.md index c44c29c9ac..c772ea65a4 100644 --- a/_overviews/scala3-book/types-generics.md +++ b/_overviews/scala3-book/types-generics.md @@ -3,7 +3,7 @@ title: Generics type: section description: This section introduces and demonstrates generics in Scala 3. languages: [ru, zh-cn] -num: 49 +num: 50 previous-page: types-inferred next-page: types-intersection --- diff --git a/_overviews/scala3-book/types-inferred.md b/_overviews/scala3-book/types-inferred.md index 828907d048..50cdb729e1 100644 --- a/_overviews/scala3-book/types-inferred.md +++ b/_overviews/scala3-book/types-inferred.md @@ -3,7 +3,7 @@ title: Inferred Types type: section description: This section introduces and demonstrates inferred types in Scala 3 languages: [ru, zh-cn] -num: 48 +num: 49 previous-page: types-introduction next-page: types-generics --- diff --git a/_overviews/scala3-book/types-intersection.md b/_overviews/scala3-book/types-intersection.md index 66a6f3ec0d..4d3f21aa31 100644 --- a/_overviews/scala3-book/types-intersection.md +++ b/_overviews/scala3-book/types-intersection.md @@ -3,7 +3,7 @@ title: Intersection Types type: section description: This section introduces and demonstrates intersection types in Scala 3. languages: [ru, zh-cn] -num: 50 +num: 51 previous-page: types-generics next-page: types-union --- diff --git a/_overviews/scala3-book/types-introduction.md b/_overviews/scala3-book/types-introduction.md index f5267d7eb2..ef21c8b4f3 100644 --- a/_overviews/scala3-book/types-introduction.md +++ b/_overviews/scala3-book/types-introduction.md @@ -3,7 +3,7 @@ title: Types and the Type System type: chapter description: This chapter provides an introduction to Scala 3 types and the type system. languages: [ru, zh-cn] -num: 47 +num: 48 previous-page: fp-summary next-page: types-inferred --- diff --git a/_overviews/scala3-book/types-opaque-types.md b/_overviews/scala3-book/types-opaque-types.md index cf25539c3f..0bc606d007 100644 --- a/_overviews/scala3-book/types-opaque-types.md +++ b/_overviews/scala3-book/types-opaque-types.md @@ -3,7 +3,7 @@ title: Opaque Types type: section description: This section introduces and demonstrates opaque types in Scala 3. languages: [zh-cn] -num: 54 +num: 55 previous-page: types-variance next-page: types-structural --- diff --git a/_overviews/scala3-book/types-others.md b/_overviews/scala3-book/types-others.md index 30447a4315..3e70eb46f6 100644 --- a/_overviews/scala3-book/types-others.md +++ b/_overviews/scala3-book/types-others.md @@ -3,7 +3,7 @@ title: Other Types type: section description: This section mentions other advanced types in Scala 3. languages: [zh-cn] -num: 57 +num: 58 previous-page: types-dependent-function next-page: ca-contextual-abstractions-intro --- diff --git a/_overviews/scala3-book/types-structural.md b/_overviews/scala3-book/types-structural.md index 8acdbc1725..5dfc73d1af 100644 --- a/_overviews/scala3-book/types-structural.md +++ b/_overviews/scala3-book/types-structural.md @@ -3,7 +3,7 @@ title: Structural Types type: section description: This section introduces and demonstrates structural types in Scala 3. languages: [zh-cn] -num: 55 +num: 56 previous-page: types-opaque-types next-page: types-dependent-function --- diff --git a/_overviews/scala3-book/types-union.md b/_overviews/scala3-book/types-union.md index 50c5919980..b61de27be9 100644 --- a/_overviews/scala3-book/types-union.md +++ b/_overviews/scala3-book/types-union.md @@ -3,7 +3,7 @@ title: Union Types type: section description: This section introduces and demonstrates union types in Scala 3. languages: [ru, zh-cn] -num: 51 +num: 52 previous-page: types-intersection next-page: types-adts-gadts scala3: true diff --git a/_overviews/scala3-book/types-variance.md b/_overviews/scala3-book/types-variance.md index 9fd69a2802..7aae5b5fac 100644 --- a/_overviews/scala3-book/types-variance.md +++ b/_overviews/scala3-book/types-variance.md @@ -3,7 +3,7 @@ title: Variance type: section description: This section introduces and demonstrates variance in Scala 3. languages: [zh-cn] -num: 53 +num: 54 previous-page: types-adts-gadts next-page: types-opaque-types --- diff --git a/_overviews/scala3-book/where-next.md b/_overviews/scala3-book/where-next.md index 41bdf27255..05bdad479a 100644 --- a/_overviews/scala3-book/where-next.md +++ b/_overviews/scala3-book/where-next.md @@ -3,7 +3,7 @@ title: Where To Go Next type: chapter description: Where to go next after reading the Scala Book languages: [zh-cn] -num: 75 +num: 76 previous-page: scala-for-python-devs next-page: --- From e4b274d9f299d803c37fd53894b3532a05b7d3c1 Mon Sep 17 00:00:00 2001 From: Stephen Layland Date: Sun, 11 Jun 2023 01:22:34 -0700 Subject: [PATCH 2/8] fix prev-page link in control-structures, minor tweaks/typo fixes to string-interpolation docs --- _overviews/scala3-book/control-structures.md | 2 +- .../scala3-book/string-interpolation.md | 78 ++++++++++++------- 2 files changed, 50 insertions(+), 30 deletions(-) diff --git a/_overviews/scala3-book/control-structures.md b/_overviews/scala3-book/control-structures.md index 2b86698980..fe94b30dc1 100644 --- a/_overviews/scala3-book/control-structures.md +++ b/_overviews/scala3-book/control-structures.md @@ -4,7 +4,7 @@ type: chapter description: This page provides an introduction to Scala's control structures, including if/then/else, 'for' loops, 'for' expressions, 'match' expressions, try/catch/finally, and 'while' loops. languages: [ru, zh-cn] num: 19 -previous-page: first-look-at-types +previous-page: string-interpolation next-page: domain-modeling-intro --- diff --git a/_overviews/scala3-book/string-interpolation.md b/_overviews/scala3-book/string-interpolation.md index fab59a7dab..a1beadf9b1 100644 --- a/_overviews/scala3-book/string-interpolation.md +++ b/_overviews/scala3-book/string-interpolation.md @@ -17,9 +17,9 @@ For instance: {% tabs example-1 %} {% tab 'Scala 2 and 3' for=example-1 %} ```scala -val name = "John" +val name = "James" val age = 30 -println(s"$name is $age years old") // "John is 30 years old" +println(s"$name is $age years old") // "James is 30 years old" ``` {% endtab %} {% endtabs %} @@ -44,9 +44,9 @@ Prepending `s` to any string literal allows the usage of variables directly in t {% tabs example-2 %} {% tab 'Scala 2 and 3' for=example-2 %} ```scala -val name = "John" +val name = "James" val age = 30 -println(s"$name is $age years old") // "John is 30 years old" +println(s"$name is $age years old") // "James is 30 years old" ``` {% endtab %} {% endtabs %} @@ -60,7 +60,7 @@ While it may seem obvious, it's important to note here that string interpolation {% tabs example-3 %} {% tab 'Scala 2 and 3' for=example-3 %} ```scala -val name = "John" +val name = "James" val age = 30 println("$name is $age years old") // "$name is $age years old" ``` @@ -97,20 +97,43 @@ Double quotes also need to be escaped. This can be done by using triple quotes a {% tabs example-6 %} {% tab 'Scala 2 and 3' for=example-6 %} ```scala -val person = """{"name":"James"}""" +println(s"""{"name":"James"}""") // prints `{"name":"James"}` ``` {% endtab %} {% endtabs %} -which will produce the string `{"name":"James"}` when printed. +Finally, all multi-line string literals can also be interpolated + +{% tabs example-7 %} +{% tab 'Scala 2 and 3' for=example-7 %} +```scala +val name = "James" +val age = 30 + +println(s"""{ + "name": "$name", + "age": $age +}""") +``` + +This will pretty print the json as + +```json +{ + "name": "James", + "age": 30 +} +``` +{% endtab %} +{% endtabs %} ## The `f` Interpolator (`f`-Strings) Prepending `f` to any string literal allows the creation of simple formatted strings, similar to `printf` in other languages. When using the `f` -interpolator, all variable references should be followed by a `printf`-style format string, like `%d`. Let's look at an example: +interpolator, all variable references should be followed by a `printf`-style format string, like `%d`. Let's look at an example: -{% tabs example-7 %} -{% tab 'Scala 2 and 3' for=example-7 %} +{% tabs example-8 %} +{% tab 'Scala 2 and 3' for=example-8 %} ```scala val height = 1.9d val name = "James" @@ -170,8 +193,8 @@ println(f"3/19 is ${300.0/19}%0.2f%%") // Prints "3/19 is 15.79%" The raw interpolator is similar to the `s` interpolator except that it performs no escaping of literals within the string. Here's an example processed string: -{% tabs example-8 %} -{% tab 'Scala 2 and 3' for=example-8 %} +{% tabs example-9 %} +{% tab 'Scala 2 and 3' for=example-9 %} ```scala scala> s"a\nb" res0: String = @@ -183,8 +206,8 @@ b Here the `s` string interpolator replaced the characters `\n` with a return character. The `raw` interpolator will not do that. -{% tabs example-9 %} -{% tab 'Scala 2 and 3' for=example-9 %} +{% tabs example-10 %} +{% tab 'Scala 2 and 3' for=example-10 %} ```scala scala> raw"a\nb" res1: String = a\nb @@ -207,8 +230,8 @@ here's a quick example to help illustrate how they work. In Scala, all processed string literals are simple code transformations. Anytime the compiler encounters a processed string literal of the form: -{% tabs example-10 %} -{% tab 'Scala 2 and 3' for=example-10 %} +{% tabs example-11 %} +{% tab 'Scala 2 and 3' for=example-11 %} ```scala id"string content" ``` @@ -238,22 +261,18 @@ with something like: {% tab 'Scala 2' for=custom-interpolator-2 %} ```scala -// Note: We extend AnyVal to prevent runtime instantiation. See -// value class guide for more info. implicit class PointHelper(val sc: StringContext) extends AnyVal { def p(args: Any*): Point = ??? } - -val pt = p"1,-2" // Point(1.0, -2.0) ``` + +**Note:** It's important to extend `AnyVal` in Scala 2.x to prevent runtime instantiation on each interpolation. See the [value class documentation][value-class] for more. {% endtab %} {% tab 'Scala 3' for=custom-interpolator-2 %} ```scala extension (sc: StringContext) def p(args: Any*): Point = ??? - -val pt = p"1,-2" // Point(1.0, -2.0) ``` {% endtab %} @@ -300,8 +319,8 @@ processing of the string `parts` and expression `args` instead of reusing the ```scala implicit class PointHelper(val sc:StringContext) extends AnyVal { def p(args: Double*): Point = { - // reuse the `s` method and then split on ',' - val pts = sc.s(args:_*).split(",", 2).map { _.toDoubleOption.getOrElse(0.0) } + // reuse the `s`-interpolator and then split on ',' + val pts = sc.s(args: _*).split(",", 2).map { _.toDoubleOption.getOrElse(0.0) } Point(pts(0), pts(1)) } } @@ -317,8 +336,8 @@ p"${x/5}, $x" // Point(2.4, 12.0) ```scala extension (sc: StringContext) def p(args: Double*): Point = { - // reuse the `s` method and then split on ',' - val pts = sc.s(args:_*).split(",", 2).map { _.toDoubleOption.getOrElse(0.0) } + // reuse the `s`-interpolator and then split on ',' + val pts = sc.s(args: _*).split(",", 2).map { _.toDoubleOption.getOrElse(0.0) } Point(pts(0), pts(1)) } @@ -332,8 +351,9 @@ p"${x/5}, $x" // Point(2.4, 12.0) While string interpolators were originally used to create some form of a String, the use of custom interpolators as above can allow for powerful syntactic shorthand, and the -community has already made swift use of this syntax for things like ansi terminal color -expansion, executing sql queries, magic `$"identifier"` representations, and many others. +community has already made swift use of this syntax for things like ANSI terminal color +expansion, executing SQL queries, magic `$"identifier"` representations, and many others. -[java-format-docs][https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Formatter.html#detail] +[java-format-docs]: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Formatter.html#detail +[value-class]: {% link _overviews/core/value-classes.md %} [sip-11]: {% link _sips/sips/string-interpolation.md %} From b2fdb3b35610658fcaf02ec0da7088f566367b01 Mon Sep 17 00:00:00 2001 From: Stephen Layland Date: Sun, 11 Jun 2023 02:57:26 -0700 Subject: [PATCH 3/8] Add redirect, fix compile errors --- _overviews/core/string-interpolation.md | 7 ++++++ .../scala3-book/string-interpolation.md | 22 +++++++++---------- 2 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 _overviews/core/string-interpolation.md diff --git a/_overviews/core/string-interpolation.md b/_overviews/core/string-interpolation.md new file mode 100644 index 0000000000..3784f5f26a --- /dev/null +++ b/_overviews/core/string-interpolation.md @@ -0,0 +1,7 @@ +--- +layout: singlepage-overview +title: String Interpolation +permalink: /overviews/core/:title.html +redirect_to: + - /scala3/book/string-interpolation.html +--- diff --git a/_overviews/scala3-book/string-interpolation.md b/_overviews/scala3-book/string-interpolation.md index a1beadf9b1..f95760ae66 100644 --- a/_overviews/scala3-book/string-interpolation.md +++ b/_overviews/scala3-book/string-interpolation.md @@ -1,8 +1,7 @@ --- title: String Interpolation type: chapter -description: This page provides more information about creating strings and using string -interpolation. +description: This page provides more information about creating strings and using string interpolation. languages: [es, ja, zh-cn] num: 18 previous-page: first-look-at-types @@ -72,9 +71,9 @@ String interpolators can also take arbitrary expressions. For example: {% tabs example-4 %} {% tab 'Scala 2 and 3' for=example-4 %} ```scala -println(s"2 + 2 = ${2 + 2}") // prints "2 + 2 = 4" +println(s"2 + 2 = ${2 + 2}") // "2 + 2 = 4" val x = -1 -println(s"x.abs = ${x.abs}") // prints "x.abs = 1" +println(s"x.abs = ${x.abs}") // "x.abs = 1" ``` {% endtab %} {% endtabs %} @@ -87,7 +86,7 @@ To represent an actual dollar sign you can double it `$$`, like here: {% tabs example-5 %} {% tab 'Scala 2 and 3' for=example-5 %} ```scala -println(s"New offers starting at $$14.99") // prints "New offers starting at $14.99" +println(s"New offers starting at $$14.99") // "New offers starting at $14.99" ``` {% endtab %} {% endtabs %} @@ -97,7 +96,7 @@ Double quotes also need to be escaped. This can be done by using triple quotes a {% tabs example-6 %} {% tab 'Scala 2 and 3' for=example-6 %} ```scala -println(s"""{"name":"James"}""") // prints `{"name":"James"}` +println(s"""{"name":"James"}""") // `{"name":"James"}` ``` {% endtab %} {% endtabs %} @@ -137,7 +136,7 @@ interpolator, all variable references should be followed by a `printf`-style for ```scala val height = 1.9d val name = "James" -println(f"$name%s is $height%2.2f meters tall") // James is 1.90 meters tall +println(f"$name%s is $height%2.2f meters tall") // "James is 1.90 meters tall" ``` {% endtab %} {% endtabs %} @@ -182,9 +181,9 @@ definition a formatter of `%s` (`String`) is assumed. Finally, as in Java, use `%%` to get a literal `%` character in the output string: {% tabs literal-percent %} -{% tab 'Scala 3' for=literal-percent %} +{% tab 'Scala 2 and 3' for=literal-percent %} ```scala -println(f"3/19 is ${300.0/19}%0.2f%%") // Prints "3/19 is 15.79%" +println(f"3/19 is less than 20%%") // "3/19 is less than 20%" ``` {% endtab %} {% endtabs %} @@ -257,7 +256,7 @@ val pt = p"1,-2" // Point(1.0,-2.0) We'd create a custom `p`-interpolator by first implementing a `StringContext` extension with something like: -{% tabs custom-interpolator class=tabs-scala-version %} +{% tabs custom-interpolator-2 class=tabs-scala-version %} {% tab 'Scala 2' for=custom-interpolator-2 %} ```scala @@ -266,7 +265,8 @@ implicit class PointHelper(val sc: StringContext) extends AnyVal { } ``` -**Note:** It's important to extend `AnyVal` in Scala 2.x to prevent runtime instantiation on each interpolation. See the [value class documentation][value-class] for more. +**Note:** It's important to extend `AnyVal` in Scala 2.x to prevent runtime instantiation on each interpolation. See the [value class]({% link _overviews/core/value-classes.md %}) documentation for more. + {% endtab %} {% tab 'Scala 3' for=custom-interpolator-2 %} From 4ca88cc28d0ee7c63c143e5598acce482ad00682 Mon Sep 17 00:00:00 2001 From: Stephen Layland Date: Sun, 11 Jun 2023 11:56:11 -0700 Subject: [PATCH 4/8] use redirect_from instead of redirect_to --- _overviews/core/string-interpolation.md | 7 ------- _overviews/scala3-book/string-interpolation.md | 2 ++ 2 files changed, 2 insertions(+), 7 deletions(-) delete mode 100644 _overviews/core/string-interpolation.md diff --git a/_overviews/core/string-interpolation.md b/_overviews/core/string-interpolation.md deleted file mode 100644 index 3784f5f26a..0000000000 --- a/_overviews/core/string-interpolation.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -layout: singlepage-overview -title: String Interpolation -permalink: /overviews/core/:title.html -redirect_to: - - /scala3/book/string-interpolation.html ---- diff --git a/_overviews/scala3-book/string-interpolation.md b/_overviews/scala3-book/string-interpolation.md index f95760ae66..cf59e128ef 100644 --- a/_overviews/scala3-book/string-interpolation.md +++ b/_overviews/scala3-book/string-interpolation.md @@ -6,6 +6,8 @@ languages: [es, ja, zh-cn] num: 18 previous-page: first-look-at-types next-page: control-structures +redirect_from: + - /overviews/core/string-interpolation.html --- ## Introduction From 4ba8c657d3534dcdce88556975a04aaac244770e Mon Sep 17 00:00:00 2001 From: Stephen Layland Date: Tue, 13 Jun 2023 09:59:31 -0700 Subject: [PATCH 5/8] Update w/ pr comments --- .../scala3-book/string-interpolation.md | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/_overviews/scala3-book/string-interpolation.md b/_overviews/scala3-book/string-interpolation.md index cf59e128ef..d7a1513650 100644 --- a/_overviews/scala3-book/string-interpolation.md +++ b/_overviews/scala3-book/string-interpolation.md @@ -2,7 +2,7 @@ title: String Interpolation type: chapter description: This page provides more information about creating strings and using string interpolation. -languages: [es, ja, zh-cn] +languages: [] num: 18 previous-page: first-look-at-types next-page: control-structures @@ -12,7 +12,7 @@ redirect_from: ## Introduction -String interpolation provides a very readable way to use variables inside strings. +String interpolation provides a way to use variables inside strings. For instance: {% tabs example-1 %} @@ -25,7 +25,7 @@ println(s"$name is $age years old") // "James is 30 years old" {% endtab %} {% endtabs %} -Using string interpolation is as simple as putting an `s` in front of your string +Using string interpolation consists of putting an `s` in front of your string quotes, and prefixing any variable names with a `$` symbol. ### Other interpolators @@ -35,8 +35,8 @@ provides. Scala provides three string interpolation methods out of the box: `s`, `f` and `raw`. Further, a string interpolator is a just special method so it is possible to define your -own. For instance, some database libraries define the very powerful `sql` interpolator -which returns the result of a database query. +own. For instance, some database libraries define a `sql` interpolator that returns a +database query. ## The `s` Interpolator (`s`-Strings) @@ -222,7 +222,7 @@ In addition to the three default string interpolators, users can define their ow ## Advanced Usage -The literal `s"Hi $name"` is parsed by scala as a _processed_ string literal. +The literal `s"Hi $name"` is parsed by Scala as a _processed_ string literal. This means that the compiler does some additional work to this literal. The specifics of processed strings and string interpolation are described in [SIP-11][sip-11], but here's a quick example to help illustrate how they work. @@ -248,7 +248,7 @@ As a trivial example, let's assume we have a simple `Point` class and want to cr {% tabs custom-interpolator-1 %} {% tab 'Scala 2 and 3' for=custom-interpolator-1 %} ```scala -case class Point(x:Double, y:Double) +case class Point(x: Double, y: Double) val pt = p"1,-2" // Point(1.0,-2.0) ``` @@ -281,26 +281,28 @@ extension (sc: StringContext) {% endtabs %} Once this extension is in scope and the Scala compiler encounters `p"some string"`, it -will process `some $string` to turn it into String tokens and expression arguments. -For example, `p"1, $var"` would turn into: +will process `some string` to turn it into String tokens and expression arguments for +each embedded variable in the string. + +For example, `p"1, $someVar"` would turn into: {% tabs extension-desugaring class=tabs-scala-version %} {% tab 'Scala 2' for=extension-desugaring %} ```scala -new StringContext("1, ", "").p(var) +new StringContext("1, ", "").p(someVar) ``` The implicit class is then used to rewrite it to the following: ```scala -new PointHelper(new StringContext("1, ", "")).p(var) +new PointHelper(new StringContext("1, ", "")).p(someVar) ``` {% endtab %} {% tab 'Scala 3' for=extension-desugaring %} ```scala -StringContext("1, ","").p(var) +StringContext("1, ","").p(someVar) ``` {% endtab %} @@ -319,7 +321,7 @@ processing of the string `parts` and expression `args` instead of reusing the {% tab 'Scala 2' for=naive-implementation %} ```scala -implicit class PointHelper(val sc:StringContext) extends AnyVal { +implicit class PointHelper(val sc: StringContext) extends AnyVal { def p(args: Double*): Point = { // reuse the `s`-interpolator and then split on ',' val pts = sc.s(args: _*).split(",", 2).map { _.toDoubleOption.getOrElse(0.0) } From eb42a918e0778a1a085f24043be4395f7b59c6c5 Mon Sep 17 00:00:00 2001 From: Stephen Layland Date: Tue, 13 Jun 2023 10:02:31 -0700 Subject: [PATCH 6/8] add final section header --- _overviews/scala3-book/string-interpolation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_overviews/scala3-book/string-interpolation.md b/_overviews/scala3-book/string-interpolation.md index d7a1513650..66f01ee21b 100644 --- a/_overviews/scala3-book/string-interpolation.md +++ b/_overviews/scala3-book/string-interpolation.md @@ -312,6 +312,8 @@ As a result, each of the fragments of the processed String are exposed in the `StringContext.parts` member, while any expressions values in the string are passed in to the method's `args` parameter. +### Example Implementation + A naive implementation of our Point interpolator method might look something like below, though a more sophisticated method may choose to have more precise control over the processing of the string `parts` and expression `args` instead of reusing the From dc03bacfdda050c5568df868216e5f2c0b94b308 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 20 Jun 2023 12:46:14 +0200 Subject: [PATCH 7/8] fix links, improve readability --- .../scala3-book/string-interpolation.md | 19 ++--- _ru/scala3/book/first-look-at-types.md | 78 +++++++++---------- .../scala3-book/first-look-at-types.md | 2 +- 3 files changed, 46 insertions(+), 53 deletions(-) diff --git a/_overviews/scala3-book/string-interpolation.md b/_overviews/scala3-book/string-interpolation.md index 66f01ee21b..7cfdc52369 100644 --- a/_overviews/scala3-book/string-interpolation.md +++ b/_overviews/scala3-book/string-interpolation.md @@ -108,22 +108,15 @@ Finally, all multi-line string literals can also be interpolated {% tabs example-7 %} {% tab 'Scala 2 and 3' for=example-7 %} ```scala -val name = "James" -val age = 30 - -println(s"""{ - "name": "$name", - "age": $age -}""") +println(s"""name: "$name", + |age: $age""".stripMargin) ``` -This will pretty print the json as +This will print as follows: -```json -{ - "name": "James", - "age": 30 -} +``` +name: "James" +age: 30 ``` {% endtab %} {% endtabs %} diff --git a/_ru/scala3/book/first-look-at-types.md b/_ru/scala3/book/first-look-at-types.md index c1bbe20d4b..a0170478f5 100644 --- a/_ru/scala3/book/first-look-at-types.md +++ b/_ru/scala3/book/first-look-at-types.md @@ -15,35 +15,35 @@ next-page: control-structures ## Все значения имеют тип -В Scala все значения имеют тип, включая числовые значения и функции. +В Scala все значения имеют тип, включая числовые значения и функции. На приведенной ниже диаграмме показано подмножество иерархии типов. Scala 3 Type Hierarchy ## Иерархия типов Scala -`Any` - это супертип всех типов, также называемый **верхним типом** (**the top type**). +`Any` - это супертип всех типов, также называемый **верхним типом** (**the top type**). Он определяет универсальные методы, такие как `equals`, `hashCode` и `toString`. -У верхнего типа `Any` есть подтип [`Matchable`][matchable], который используется для обозначения всех типов, -для которых возможно выполнить pattern matching (сопоставление с образцом). -Важно гарантировать вызов свойства _“параметричность”_, что вкратце означает, -что мы не можем сопоставлять шаблоны для значений типа `Any`, а только для значений, которые являются подтипом `Matchable`. +У верхнего типа `Any` есть подтип [`Matchable`][matchable], который используется для обозначения всех типов, +для которых возможно выполнить pattern matching (сопоставление с образцом). +Важно гарантировать вызов свойства _“параметричность”_, что вкратце означает, +что мы не можем сопоставлять шаблоны для значений типа `Any`, а только для значений, которые являются подтипом `Matchable`. [Справочная документация][matchable] содержит более подробную информацию о `Matchable`. `Matchable` содержит два важных подтипа: `AnyVal` и `AnyRef`. -*`AnyVal`* представляет типы значений. -Существует несколько предопределенных типов значений, и они non-nullable: -`Double`, `Float`, `Long`, `Int`, `Short`, `Byte`, `Char`, `Unit` и `Boolean`. +*`AnyVal`* представляет типы значений. +Существует несколько предопределенных типов значений, и они non-nullable: +`Double`, `Float`, `Long`, `Int`, `Short`, `Byte`, `Char`, `Unit` и `Boolean`. `Unit` - это тип значения, который не несет никакой значимой информации. Существует ровно один экземпляр `Unit` - `()`. -*`AnyRef`* представляет ссылочные типы. Все типы, не являющиеся значениями, определяются как ссылочные типы. -Каждый пользовательский тип в Scala является подтипом `AnyRef`. +*`AnyRef`* представляет ссылочные типы. Все типы, не являющиеся значениями, определяются как ссылочные типы. +Каждый пользовательский тип в Scala является подтипом `AnyRef`. Если Scala используется в контексте среды выполнения Java, `AnyRef` соответствует `java.lang.Object`. -В языках, основанных на операторах, `void` используется для методов, которые ничего не возвращают. -В Scala для методов, которые не имеют возвращаемого значения, +В языках, основанных на операторах, `void` используется для методов, которые ничего не возвращают. +В Scala для методов, которые не имеют возвращаемого значения, такие как следующий метод, для той же цели используется `Unit`: {% tabs unit %} @@ -54,7 +54,7 @@ def printIt(a: Any): Unit = println(a) {% endtab %} {% endtabs %} -Вот пример, демонстрирующий, что строки, целые числа, символы, логические значения и функции являются экземплярами `Any` +Вот пример, демонстрирующий, что строки, целые числа, символы, логические значения и функции являются экземплярами `Any` и могут обрабатываться так же, как и любой другой объект: {% tabs any %} @@ -73,8 +73,8 @@ list.foreach(element => println(element)) {% endtab %} {% endtabs %} -Код определяет список значений типа `List[Any]`. -Список инициализируется элементами различных типов, но каждый из них является экземпляром `scala.Any`, +Код определяет список значений типа `List[Any]`. +Список инициализируется элементами различных типов, но каждый из них является экземпляром `scala.Any`, поэтому мы можем добавить их в список. Вот вывод программы: @@ -89,7 +89,7 @@ true ## Типы значений в Scala -Как показано выше, числовые типы Scala расширяют `AnyVal`, и все они являются полноценными объектами. +Как показано выше, числовые типы Scala расширяют `AnyVal`, и все они являются полноценными объектами. В этих примерах показано, как объявлять переменные этих числовых типов: {% tabs anyval %} @@ -105,9 +105,9 @@ val f: Float = 3.0 {% endtab %} {% endtabs %} -В первых четырех примерах, если явно не указать тип, то тип числа `1` по умолчанию будет равен `Int`, -поэтому, если нужен один из других типов данных — `Byte`, `Long` или `Short` — необходимо явно объявить эти типы. -Числа с десятичной дробью (например, `2.0`) по умолчанию будут иметь тип `Double`, +В первых четырех примерах, если явно не указать тип, то тип числа `1` по умолчанию будет равен `Int`, +поэтому, если нужен один из других типов данных — `Byte`, `Long` или `Short` — необходимо явно объявить эти типы. +Числа с десятичной дробью (например, `2.0`) по умолчанию будут иметь тип `Double`, поэтому, если необходим `Float`, нужно объявить `Float` явно, как показано в последнем примере. Поскольку `Int` и `Double` являются числовыми типами по умолчанию, их можно создавать без явного объявления типа данных: @@ -121,7 +121,7 @@ val x = 1.0 // по умолчанию Double {% endtab %} {% endtabs %} -Также можно добавить символы `L`, `D`, and `F` (или их эквивалент в нижнем регистре) +Также можно добавить символы `L`, `D`, and `F` (или их эквивалент в нижнем регистре) для того, чтобы задать `Long`, `Double` или `Float` значения: {% tabs type-post %} @@ -145,7 +145,7 @@ val c = 'a' {% endtab %} {% endtabs %} -Как показано, заключайте строки в двойные кавычки или тройные кавычки для многострочных строк, +Как показано, заключайте строки в двойные кавычки или тройные кавычки для многострочных строк, а одиночный символ заключайте в одинарные кавычки. Типы данных и их диапазоны: @@ -176,7 +176,7 @@ val b = BigDecimal(123_456.789) {% endtab %} {% endtabs %} -Где `Double` и `Float` являются приблизительными десятичными числами, +Где `Double` и `Float` являются приблизительными десятичными числами, а `BigDecimal` используется для точной арифметики, например, при работе с валютой. `BigInt` и `BigDecimal` поддерживают все привычные числовые операторы: @@ -200,7 +200,7 @@ val d = b * b // scala.math.BigInt = 1524157875019052100 ### Интерполяция строк -Интерполяция строк обеспечивает очень удобный способ использования переменных внутри строк. +Интерполяция строк обеспечивает очень удобный способ использования переменных внутри строк. Например, учитывая эти три переменные: {% tabs string-inside1 %} @@ -239,9 +239,9 @@ println(s"x.abs = ${x.abs}") // печатает "x.abs = 1" #### Другие интерполяторы -То `s`, что вы помещаете перед строкой, является лишь одним из возможных интерполяторов. -Если вы используете `f` вместо `s`, вы можете использовать `printf` - синтаксис форматирования стиля в строке. -Кроме того, строковый интерполятор — это всего лишь специальный метод, и вы можете определить свой собственный. +То `s`, что вы помещаете перед строкой, является лишь одним из возможных интерполяторов. +Если вы используете `f` вместо `s`, вы можете использовать `printf` - синтаксис форматирования стиля в строке. +Кроме того, строковый интерполятор — это всего лишь специальный метод, и вы можете определить свой собственный. Например, некоторые библиотеки баз данных определяют очень мощный интерполятор `sql`. ### Многострочные строки @@ -314,7 +314,7 @@ val number: Int = face // 9786 {% endtab %} {% endtabs %} -Вы можете привести к типу, только если нет потери информации. +Вы можете привести к типу, только если нет потери информации. В противном случае вам нужно четко указать приведение типов: {% tabs cast2 %} @@ -327,29 +327,29 @@ val z: Long = y // Ошибка {% endtab %} {% endtabs %} -Вы также можете привести ссылочный тип к подтипу. +Вы также можете привести ссылочный тип к подтипу. Это будет рассмотрено в книге позже. ## `Nothing` и `null` -`Nothing` является подтипом всех типов, также называемым **нижним типом** (**the bottom type**). -Нет значения, которое имело бы тип `Nothing`. -Он обычно сигнализирует о прекращении, таком как thrown exception, выходе из программы или бесконечном цикле - +`Nothing` является подтипом всех типов, также называемым **нижним типом** (**the bottom type**). +Нет значения, которое имело бы тип `Nothing`. +Он обычно сигнализирует о прекращении, таком как thrown exception, выходе из программы или бесконечном цикле - т.е. это тип выражения, который не вычисляется до определенного значения, или метод, который нормально не возвращается. -`Null` - это подтип всех ссылочных типов (т.е. любой подтип `AnyRef`). -Он имеет единственное значение, определяемое ключевым словом `null`. -В настоящее время применение `null` считается плохой практикой. -Его следует использовать в основном для взаимодействия с другими языками JVM. -Опция компилятора `opt-in` изменяет статус `Null`, делая все ссылочные типы non-nullable. +`Null` - это подтип всех ссылочных типов (т.е. любой подтип `AnyRef`). +Он имеет единственное значение, определяемое ключевым словом `null`. +В настоящее время применение `null` считается плохой практикой. +Его следует использовать в основном для взаимодействия с другими языками JVM. +Опция компилятора `opt-in` изменяет статус `Null`, делая все ссылочные типы non-nullable. Этот параметр может [стать значением по умолчанию][safe-null] в будущей версии Scala. -В то же время `null` почти никогда не следует использовать в коде Scala. +В то же время `null` почти никогда не следует использовать в коде Scala. Альтернативы `null` обсуждаются в главе о [функциональном программировании][fp] и в [документации API][option-api]. [reference]: {{ site.scala3ref }}/overview.html [matchable]: {{ site.scala3ref }}/other-new-features/matchable.html -[interpolation]: {% link _overviews/core/string-interpolation.md %} +[interpolation]: {% link _overviews/scala3-book/string-interpolation.md %} [fp]: {% link _overviews/scala3-book/fp-intro.md %} [option-api]: https://scala-lang.org/api/3.x/scala/Option.html [safe-null]: {{ site.scala3ref }}/experimental/explicit-nulls.html diff --git a/_zh-cn/overviews/scala3-book/first-look-at-types.md b/_zh-cn/overviews/scala3-book/first-look-at-types.md index 666426ff87..a2c876654b 100644 --- a/_zh-cn/overviews/scala3-book/first-look-at-types.md +++ b/_zh-cn/overviews/scala3-book/first-look-at-types.md @@ -370,7 +370,7 @@ val z: Long = y // Error [reference]: {{ site.scala3ref }}/overview.html [matchable]: {{ site.scala3ref }}/other-new-features/matchable.html -[interpolation]: {% link _overviews/core/string-interpolation.md %} +[interpolation]: {% link _overviews/scala3-book/string-interpolation.md %} [fp]: {% link _zh-cn/overviews/scala3-book/fp-intro.md %} [option-api]: https://scala-lang.org/api/3.x/scala/Option.html [safe-null]: {{ site.scala3ref }}/experimental/explicit-nulls.html From 1ab0efbcdeeaf8b5bfa7547cd1d3907e8ceda649 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 20 Jun 2023 12:49:03 +0200 Subject: [PATCH 8/8] fix redirect from scala 2 book --- _overviews/scala-book/two-notes-about-strings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala-book/two-notes-about-strings.md b/_overviews/scala-book/two-notes-about-strings.md index 131c37f4f1..31a097f758 100644 --- a/_overviews/scala-book/two-notes-about-strings.md +++ b/_overviews/scala-book/two-notes-about-strings.md @@ -9,7 +9,7 @@ num: 11 outof: 54 previous-page: built-in-types next-page: command-line-io -new-version: /scala3/book/first-look-at-types.html#two-notes-about-strings +new-version: /scala3/book/first-look-at-types.html#strings ---