2011-10-29 23 views
39

ser nuevo en Scala (2.9.1), tengo un List[Event] y me gustaría copiarlo en un Queue[Event], pero la siguiente sintaxis produce una vez Queue[List[Event]]:¿Qué significa param: _ * en Scala?

val eventQueue = Queue(events) 

Por alguna razón, las siguientes obras:

val eventQueue = Queue(events : _*) 

Pero me gustaría saber qué hace y por qué funciona? Ya he mirado en la firma de la función Queue.apply:

def apply[A](elems: A*) 

Y entiendo por qué el primer intento no funciona, pero ¿cuál es el significado de la segunda? ¿Qué es :, y _* en este caso, y por qué la función apply simplemente toma un Iterable[A]?

Respuesta

40

a: A es tipo de adscripción; ver What is the purpose of type ascriptions in Scala?

: _* es una instancia especial de la adscripción de tipo que le dice al compilador que trate un único argumento de un tipo de secuencia como una secuencia de argumento variable, es decir, varargs.

es completamente válida para crear un Queue usando Queue.apply que tiene un solo elemento que es una secuencia o iterable, así que esto es exactamente lo que sucede cuando se da una sola Iterable[A].

+1

¡Gracias por indicarme que escriba adscripción! – Chris

34

Esta es una notación especial que le dice al compilador que pase cada elemento como su propio argumento, en lugar de todo como un único argumento. Ver here.

Es una anotación de tipo que indica un argumento de secuencia y se menciona como una "excepción" a la regla general en la sección 4.6.2 de la especificación de idioma, "Parámetros repetidos".

Es útil cuando una función toma una cantidad variable de argumentos, p. una función como def sum(args: Int*), que puede ser invocada como sum(1), sum(1,2) etc Si usted tiene una lista como xs = List(1,2,3), no se puede pasar xs sí mismo, porque es un List en lugar de un Int, pero se puede pasar a sus elementos usando sum(xs: _*).

+3

también una gran respuesta, gracias y upvote – Chris

+0

'suma def (xs: _ *)' lanza 'error: no unido tipo comodín' – 7kemZmani

+0

Su respuesta es clara, pero esto en realidad me está creando más confusión, por lo general en scala 'xs: int' significa que el tipo de xs es int, pasando a que es lo anterior una sintaxis en scala donde' xs: _ * 'significa que xs se transfiere a sus miembros individuales. – Rpant

0

Para la gente de Python:

operador de Scala _* es más o menos el equivalente de Python de *-operator.


Ejemplo

la conversión el ejemplo Scala de la link proporcionada por Luigi Plinge:

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

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

a Python se vería así:

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

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

y ambos dar el followin g salida:

What's
up
doc?


La diferencia: desembalaje parámetros posicionales

Mientras * -operator de Python también puede ocuparse de desembalaje de posicionales parámetros/parámetros para las funciones-Arity fijo:

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

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

8

D ue va lo mismo con Scala:

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

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

fallará:

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

pero es posible lograr lo mismo con Scala:

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

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

Según Lorrin Nelson así es como funciona:

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 lectura: