Skip to content

Rewrote local type inference tour #737

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 0 additions & 63 deletions tutorials/tour/_posts/2017-02-13-local-type-inference.md

This file was deleted.

63 changes: 63 additions & 0 deletions tutorials/tour/_posts/2017-02-13-type-inference.md
Original file line number Diff line number Diff line change
@@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of "type of a value", suggest "type of an expression"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and I'm not sure "You'll often see this with variables and return types" really adds any meaning?


## 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/an int/an Int/


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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/can never infer/never infers/ — slightly different shade of meaning


```
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`.
Copy link
Member

@SethTisue SethTisue Mar 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seq is missing backquotes around it. unless you just want to use the ordinary noun "sequence"

s/int/Int/ — unless you are really just using it as a noun, in which case "integer" not "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:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary to call something "quite dangerous" unless it compiles, yet fails at runtime.

I'd suggest: "In some situations, the compiler may infer a type that wasn't the one you intended."

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add to your suggestion: "Therefore, we recommended that you make the type explicit for any APIs that will be exposed to users of your code" or something similar.


```tut:fail
object InferenceTest4 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the object wrapper needed here?

var obj = null
obj = new Object()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new AnyRef is more idiomatic Scala than 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.