122

Being new to Scala (2.9.1), I have a List[Event] and would like to copy it into a Queue[Event], but the following Syntax yields a Queue[List[Event]] instead:

val eventQueue = Queue(events)

For some reason, the following works:

val eventQueue = Queue(events : _*)

But I would like to understand what it does, and why it works? I already looked at the signature of the Queue.apply function:

def apply[A](elems: A*)

And I understand why the first attempt doesn't work, but what's the meaning of the second one? What is :, and _* in this case, and why doesn't the apply function just take an Iterable[A] ?

Micho
  • 3,929
  • 13
  • 37
  • 40
Chris
  • 2,057
  • 2
  • 16
  • 20

3 Answers3

117

a: A is type ascription; see What is the purpose of type ascriptions in Scala?

: _* 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.

It is completely valid to create a Queue using Queue.apply that has a single element which is a sequence or iterable, so this is exactly what happens when you give a single Iterable[A].

Community
  • 1
  • 1
Ben James
  • 121,135
  • 26
  • 193
  • 155
  • so: ¿`a: _*` is like the spread operator of javascript `...a`? beign `a` a collection. You may see spread operator here -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax – Victor Jun 02 '22 at 12:51
101

This is a special notation that tells the compiler to pass each element as its own argument, rather than all of it as a single argument. See here.

It is a type annotation that indicates a sequence argument and is mentioned as an "exception" to the general rule in section 4.6.2 of the language spec, "Repeated Parameters".

It is useful when a function takes a variable number of arguments, e.g. a function such as def sum(args: Int*), which can be invoked as sum(1), sum(1,2) etc. If you have a list such as xs = List(1,2,3), you can't pass xs itself, because it is a List rather than an Int, but you can pass its elements using sum(xs: _*).

Luigi Plinge
  • 50,650
  • 20
  • 113
  • 180
  • `def sum(xs: _*)` throws 'error: unbound wildcard type' – 7kemZmani Sep 03 '17 at 04:17
  • Your answer is clear , but this is actually creating more confusion for me , usually in scala `xs: int` means type of xs is int , going by that is the above a syntax in scala where `xs: _*` means xs is casted to its individual members. – Rpant Sep 25 '17 at 04:40
  • Followed the above link and looks like thats what it is , type ascription is a scala terminology for java type casting. Please correct me if wrong. – Rpant Sep 25 '17 at 04:43
  • 3
    @7kemZmani : You have to define the function with an specific var-args type: `def sum(args: Int*)` and you call it with the wildcard "generic" var-args type: `val a = sum(xs: _*)`. Think about `_*` as "I am passing an Int*, or a String*, or anything* that is defined in the method signature" – Alfonso Nishikawa Jan 16 '20 at 10:59
22

For Python folks:

Scala's _* operator is more or less the equivalent of Python's *-operator.


Example

Converting the scala example from the link provided by Luigi Plinge:

def echo(args: String*) = 
    for (arg <- args) println(arg)

val arr = Array("What's", "up", "doc?")
echo(arr: _*)

to Python would look like:

def echo(*args):
    for arg in args:
        print "%s" % arg

arr = ["What's", "up", "doc?"]
echo(*arr)

and both give the following output:

What's
up
doc?


The Difference: unpacking positional parameters

While Python's *-operator can also deal with unpacking of positional parameters/parameters for fixed-arity functions:

def multiply (x, y):
    return x * y

operands = (2, 4)
multiply(*operands)

8

Doing the same with Scala:

def multiply(x:Int, y:Int) = {
    x * y;
}

val operands = (2, 4)
multiply (operands : _*)

will fail:

not enough arguments for method multiply: (x: Int, y: Int)Int.
Unspecified value parameter y.

But it is possible to achieve the same with scala:

def multiply(x:Int, y:Int) = {
    x*y;
}

val operands = (2, 4)
multiply _ tupled operands

According to Lorrin Nelson this is how it works:

The first part, f _, is the syntax for a partially applied function in which none of the arguments have been specified. This works as a mechanism to get a hold of the function object. tupled returns a new function which of arity-1 that takes a single arity-n tuple.

Futher reading:

Murmel
  • 5,402
  • 47
  • 53