From 4970f640e0646aec530862b156d5c4cf5ac8d788 Mon Sep 17 00:00:00 2001 From: Travis Lee Date: Fri, 17 Mar 2017 20:27:33 +0100 Subject: [PATCH] Rewrote local type inference tour --- .../_posts/2017-02-13-local-type-inference.md | 63 ------------------- .../tour/_posts/2017-02-13-type-inference.md | 63 +++++++++++++++++++ 2 files changed, 63 insertions(+), 63 deletions(-) delete mode 100644 tutorials/tour/_posts/2017-02-13-local-type-inference.md create mode 100644 tutorials/tour/_posts/2017-02-13-type-inference.md diff --git a/tutorials/tour/_posts/2017-02-13-local-type-inference.md b/tutorials/tour/_posts/2017-02-13-local-type-inference.md deleted file mode 100644 index b8096a5f2f..0000000000 --- a/tutorials/tour/_posts/2017-02-13-local-type-inference.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -layout: tutorial -title: Local Type Inference - -disqus: true - -tutorial: scala-tour -categories: tour -num: 29 -next-page: operators -previous-page: polymorphic-methods ---- -Scala has a built-in type inference mechanism which allows the programmer to omit certain type annotations. It is, for instance, often not necessary in Scala to specify the type of a variable, since the compiler can deduce the type from the initialization expression of the variable. Also return types of methods can often be omitted since they correspond to the type of the body, which gets inferred by the compiler. - -Here is an example: - -```tut -object InferenceTest1 extends App { - val x = 1 + 2 * 3 // the type of x is Int - val y = x.toString() // the type of y is String - def succ(x: Int) = x + 1 // method succ returns Int values -} -``` - -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: - -```tut:fail -object InferenceTest2 { - def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1) -} -``` - -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 is an example which illustrates this: - -``` -case class MyPair[A, B](x: A, y: B); -object InferenceTest3 extends App { - def id[T](x: T) = x - val p = MyPair(1, "scala") // type: MyPair[Int, String] - val q = id(1) // type: Int -} -``` - -The last two lines of this program are equivalent to the following code where all inferred types are made explicit: - -``` -val x: MyPair[Int, String] = MyPair[Int, String](1, "scala") -val y: Int = id[Int](1) -``` - -In some situations it can be quite dangerous to rely on Scala's type inference mechanism as the following program shows: - -```tut:fail -object InferenceTest4 { - var obj = null - obj = new Object() -} -``` - -This program does not compile because the type inferred for variable `obj` is `Null`. Since the only value of that type is `null`, it is impossible to make this variable refer to another value. - diff --git a/tutorials/tour/_posts/2017-02-13-type-inference.md b/tutorials/tour/_posts/2017-02-13-type-inference.md new file mode 100644 index 0000000000..4e8eceaead --- /dev/null +++ b/tutorials/tour/_posts/2017-02-13-type-inference.md @@ -0,0 +1,63 @@ +--- +layout: tutorial +title: Type Inference + +disqus: true + +tutorial: scala-tour +categories: tour +num: 29 +next-page: operators +previous-page: polymorphic-methods +prerequisite-knowledge: unified-types, generic-classes +--- +The Scala compiler can often infer the type of a value so you don't have to declare it explicitly. You'll often see this with variables and return types. + +## Omitting the type +``` +val businessName = "Montreux Jazz Café" +``` +The compiler can detect that `businessName` is a String. It works similarly with methods: +``` +def squareOf(x: Int) = x * x +``` +The compiler can infer that the return type is an int so no 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: + +```tut:fail +def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1) +``` + +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: +``` +case class MyPair[A, B](x: A, y: B); +val p = MyPair(1, "scala") // type: MyPair[Int, String] + +def id[T](x: T) = x +val q = id(1) // type: Int +``` +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`. + +## Parameters +The compiler can never infer method parameter types. However, in certain cases, it can infer anonymous function parameter types when the function is passed as argument. + +``` +val doubled = Seq(1, 3, 4).map(x => x * 2) // List(2, 6, 8) +``` +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 int). Therefore, the compiler can infer from `x * 2` that `B` is type `Int`. + +## When _not_ to rely on type inference + +It is generally considered more readable to declare the type of members exposed in a public API. Also, in some situations it can be quite dangerous to rely on Scala's type inference mechanism as the following program shows: + +```tut:fail +object InferenceTest4 { + var obj = null + obj = new Object() +} +``` + +This program does not compile because the type inferred for variable `obj` is `Null`. Since the only value of that type is `null`, it is impossible to make this variable refer to another value.