JRR
JRR

Reputation: 6152

can you explain this piece of Scala code?

Can someone please walk through this piece of scala syntax for me? I am new to the language, coming from Java.

val map = Map(seq map { a => a.key -> a }: _*)

In particular I understand a => a.key -> a is an anonymous function that returns a pair(?) (a.key, a) for each a, but what does : _*, { } do and why is there a space between seq and map? Are they arguments to the Map constructor?

Upvotes: 2

Views: 147

Answers (2)

Apurva Singh
Apurva Singh

Reputation: 5010

In addition to Ramesh's answer.. your seq is most likely a Scala collection. Scala collections have numerous methods like map, filter, fold, reduce etc etc. So map is a method call on seq which is called without using the dot operator. This is allowed in Scala iff the method takes a single parameter.
The _* is somewhat weirder. Immutable Map requires a vararg as parameter. But the map method on seq will return a Map. The _* is in position of "type". By type, I simply mean, if I write i: Int, so Int is the type. So when an object's type is marked as _*, automatic type conversion takes place by the compiler which uses a factory to convert the object into a vararg. Like in Java, varargs can only appear as last parameter in a parameter list.

Upvotes: 2

Ramesh Maharjan
Ramesh Maharjan

Reputation: 41987

: _* tells the compiler to pass each element of arr as its own argument to the function, rather than all of it as a single argument. Or to say in other words it is a special instance of type ascription which tells the compiler to treat a single argument of a sequence type as a variable argument sequence, i.e. varargs.

The _* type annotation is covered in "4.6.2 Repeated Parameters" of the SLS.

The last value parameter of a parameter section may be suffixed by “*”, e.g. (..., x:T *). The type of such a repeated parameter inside the method is then the sequence type scala.Seq[T]. Methods with repeated parameters T * take a variable number of arguments of type T . That is, if a method m with type (p1 : T1, . . . , pn : Tn,ps : S*)U is applied to arguments (e1, . . . , ek) where k >= n, then m is taken in that application to have type (p1 : T1, . . . , pn : Tn,ps : S, . . . , ps0S)U, with k ¡ n occurrences of type S where any parameter names beyond ps are fresh. The only exception to this rule is if the last argument is marked to be a sequence argument via a _* type annotation. If m above is applied to arguments (e1, . . . , en,e0 : _*), then the type of m in that application is taken to be (p1 : T1, . . . , pn : Tn,ps :scala.Seq[S])

{ } indicates a block of code, which is composed of multiple statements and declarations, and whose value is that of the last statement. If you need declarations, multiple statements, an import or anything like that, you need curly braces

Scala has a special punctuation-free syntax for invoking methods that take one argument. General rule is Scala methods that take a single parameter can be invoked without dots or parentheses.

Upvotes: 4

Related Questions