From 8d325fb21547cfcca0a6686ded1546e799f1eb7b Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 22 Sep 2022 22:34:07 +0200 Subject: [PATCH 1/6] Add code tabs for _tour/type-inference --- _tour/type-inference.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/_tour/type-inference.md b/_tour/type-inference.md index 271906fe3c..bcabeae411 100644 --- a/_tour/type-inference.md +++ b/_tour/type-inference.md @@ -12,26 +12,42 @@ The Scala compiler can often infer the type of an expression so you don't have t ## Omitting the type +{% tabs type-inference_1 %} +{% tab 'Scala 2 and 3' for=type-inference_1 %} ```scala mdoc val businessName = "Montreux Jazz Café" ``` +{% endtab %} +{% endtabs %} + The compiler can detect that `businessName` is a String. It works similarly with methods: +{% tabs type-inference_2 %} +{% tab 'Scala 2 and 3' for=type-inference_2 %} ```scala mdoc def squareOf(x: Int) = x * x ``` +{% endtab %} +{% endtabs %} + The compiler can infer that the return type is an `Int`, so no explicit return type is required. For recursive methods, the compiler is not able to infer a result type. Here is a program which will fail the compiler for this reason: +{% tabs type-inference_3 %} +{% tab 'Scala 2 and 3' for=type-inference_3 %} ```scala mdoc:fail def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1) ``` +{% endtab %} +{% endtabs %} It is also not compulsory to specify type parameters when [polymorphic methods](polymorphic-methods.html) are called or [generic classes](generic-classes.html) are instantiated. The Scala compiler will infer such missing type parameters from the context and from the types of the actual method/constructor parameters. Here are two examples: +{% tabs type-inference_4 %} +{% tab 'Scala 2 and 3' for=type-inference_4 %} ```scala mdoc case class MyPair[A, B](x: A, y: B) val p = MyPair(1, "scala") // type: MyPair[Int, String] @@ -39,6 +55,8 @@ val p = MyPair(1, "scala") // type: MyPair[Int, String] def id[T](x: T) = x val q = id(1) // type: Int ``` +{% endtab %} +{% endtabs %} The compiler uses the types of the arguments of `MyPair` to figure out what type `A` and `B` are. Likewise for the type of `x`. @@ -46,9 +64,13 @@ The compiler uses the types of the arguments of `MyPair` to figure out what type The compiler never infers method parameter types. However, in certain cases, it can infer anonymous function parameter types when the function is passed as argument. +{% tabs type-inference_5 %} +{% tab 'Scala 2 and 3' for=type-inference_5 %} ```scala mdoc Seq(1, 3, 4).map(x => x * 2) // List(2, 6, 8) ``` +{% endtab %} +{% endtabs %} The parameter for map is `f: A => B`. Because we put integers in the `Seq`, the compiler knows that `A` is `Int` (i.e. that `x` is an integer). Therefore, the compiler can infer from `x * 2` that `B` is type `Int`. @@ -58,14 +80,22 @@ It is generally considered more readable to declare the type of members exposed Also, type inference can sometimes infer a too-specific type. Suppose we write: -```scala +{% tabs type-inference_6 %} +{% tab 'Scala 2 and 3' for=type-inference_6 %} +```scala mdoc var obj = null ``` +{% endtab %} +{% endtabs %} We can't then go on and make this reassignment: +{% tabs type-inference_7 %} +{% tab 'Scala 2 and 3' for=type-inference_7 %} ```scala mdoc:fail obj = new AnyRef ``` +{% endtab %} +{% endtabs %} It won't compile, because the type inferred for `obj` was `Null`. Since the only value of that type is `null`, it is impossible to assign a different value. From 2e98729c624486dff3e4eed0a02735f2723ea140 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 22 Sep 2022 22:39:00 +0200 Subject: [PATCH 2/6] Update type-inference.md --- _tour/type-inference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/type-inference.md b/_tour/type-inference.md index bcabeae411..9a4a8daa07 100644 --- a/_tour/type-inference.md +++ b/_tour/type-inference.md @@ -82,7 +82,7 @@ Also, type inference can sometimes infer a too-specific type. Suppose we write: {% tabs type-inference_6 %} {% tab 'Scala 2 and 3' for=type-inference_6 %} -```scala mdoc +```scala mdoc:crash var obj = null ``` {% endtab %} From 9dbe858438d5c82b05a83d6ab0d63c52fb6082ae Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 22 Sep 2022 22:41:12 +0200 Subject: [PATCH 3/6] Update type-inference.md --- _tour/type-inference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/type-inference.md b/_tour/type-inference.md index 9a4a8daa07..8e661c27ed 100644 --- a/_tour/type-inference.md +++ b/_tour/type-inference.md @@ -82,7 +82,7 @@ Also, type inference can sometimes infer a too-specific type. Suppose we write: {% tabs type-inference_6 %} {% tab 'Scala 2 and 3' for=type-inference_6 %} -```scala mdoc:crash +```scala mdoc:fail var obj = null ``` {% endtab %} From 6deb8fcf9d6443601469006d68861e28d501bc90 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 22 Sep 2022 22:43:44 +0200 Subject: [PATCH 4/6] Update type-inference.md --- _tour/type-inference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/type-inference.md b/_tour/type-inference.md index 8e661c27ed..bcabeae411 100644 --- a/_tour/type-inference.md +++ b/_tour/type-inference.md @@ -82,7 +82,7 @@ Also, type inference can sometimes infer a too-specific type. Suppose we write: {% tabs type-inference_6 %} {% tab 'Scala 2 and 3' for=type-inference_6 %} -```scala mdoc:fail +```scala mdoc var obj = null ``` {% endtab %} From ac5bd9c9cc9bfb7c4f3f30845c9d936ad91f0515 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 22 Sep 2022 22:46:48 +0200 Subject: [PATCH 5/6] Update type-inference.md --- _tour/type-inference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/type-inference.md b/_tour/type-inference.md index bcabeae411..eb256f2f2f 100644 --- a/_tour/type-inference.md +++ b/_tour/type-inference.md @@ -82,7 +82,7 @@ Also, type inference can sometimes infer a too-specific type. Suppose we write: {% tabs type-inference_6 %} {% tab 'Scala 2 and 3' for=type-inference_6 %} -```scala mdoc +```scala var obj = null ``` {% endtab %} From dc0025ec069bcf1b4f6af6ac86db1d2c48233956 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 22 Sep 2022 22:54:31 +0200 Subject: [PATCH 6/6] Add code tabs for _tour/type-inference --- _tour/type-inference.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/_tour/type-inference.md b/_tour/type-inference.md index eb256f2f2f..3b5ea38cc0 100644 --- a/_tour/type-inference.md +++ b/_tour/type-inference.md @@ -34,12 +34,17 @@ The compiler can infer that the return type is an `Int`, so no explicit return t For recursive methods, the compiler is not able to infer a result type. Here is a program which will fail the compiler for this reason: -{% tabs type-inference_3 %} -{% tab 'Scala 2 and 3' for=type-inference_3 %} +{% tabs type-inference_3 class=tabs-scala-version %} +{% tab 'Scala 2' for=type-inference_3 %} ```scala mdoc:fail def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1) ``` {% endtab %} +{% tab 'Scala 3' for=type-inference_3 %} +```scala +def fac(n: Int) = if n == 0 then 1 else n * fac(n - 1) +``` +{% endtab %} {% endtabs %} It is also not compulsory to specify type parameters when [polymorphic methods](polymorphic-methods.html) are called or [generic classes](generic-classes.html) are instantiated. The Scala compiler will infer such missing type parameters from the context and from the types of the actual method/constructor parameters.