Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't Scala infer the type of _?

I heard in Scala I can use _ as "anonymous parameter" in anonymous function:

List(1,2,3).foreach(print(_))

But this code can't be compiled:

scala> def a[T](s: Seq[T]): Seq[T] = s.map(_)
<console>:7: error: missing parameter type for expanded function ((x$1) => s.map(x$1))

And this can:

scala> def a[T](s: Seq[T]): Seq[T] = s.map(x => x)
a: [T](s: Seq[T])Seq[T]

It seems about type inference. But how could x => x provide more information than _?

like image 696
Lai Yu-Hsuan Avatar asked Dec 21 '13 19:12

Lai Yu-Hsuan


People also ask

What means _ in Scala?

Scala allows the use of underscores (denoted as '_') to be used as placeholders for one or more parameters. we can consider the underscore to something that needs to be filled in with a value. However, each parameter must appear only one time within the function literal.

Does Scala have type inference?

The Scala compiler can infer the types of expressions automatically from contextual information. Therefore, we need not declare the types explicitly. This feature is commonly referred to as type inference. It helps reduce the verbosity of our code, making it more concise and readable.

What would be the type inferred by Scala compiler for variable?

Scala compiler can automatically infer types of each variable declared. If the value of a variable is declared in double-quotes it will automatically be inferred as String. Also, the compiler can infer any value in a single quote is inferred as Char.


1 Answers

The problem here is not a type inference.

As you can see from error message equivalent code for s.map(_) is not s.map(x => x), but this:

i => s.map(i)

Just like print(_) (actually Predef.print(_)) means i => Predef.print(i).

Or like "a" + _ means "a".+(_) means s => "a".+(s).

This just doesn't make sense in current context.

Let's suppose you have a list of functions String => String (fs) and you want to apply all these functions to list of String. You'll use this code:

fs.map{f => s.map(f)}

or just this:

fs.map{s.map(_)}

Addition: you could use identity method instead if x => x. It's imported by default, but you could make it even shorter using addition import:

import Predef.{identity => id}
List(1, 2, 3) map id
// List[Int] = List(1, 2, 3)

Note that identity is a well known name, so in team you should use it instead of your aliases.

like image 189
senia Avatar answered Oct 20 '22 10:10

senia