Cosa significa param: _ * in Scala?


87

Essendo nuovo in Scala (2.9.1), ho un List[Event]e vorrei copiarlo in a Queue[Event], ma la seguente sintassi restituisce Queue[List[Event]]invece a:

val eventQueue = Queue(events)

Per qualche motivo, il seguente funziona:

val eventQueue = Queue(events : _*)

Ma vorrei capire cosa fa e perché funziona? Ho già guardato la firma della Queue.applyfunzione:

def apply[A](elems: A*)

E capisco perché il primo tentativo non funziona, ma qual è il significato del secondo? Cos'è :, e _*in questo caso, e perché la applyfunzione non prende solo un Iterable[A]?

Risposte:


93

a: Aè di tipo attribuzione; vedi Qual è lo scopo delle attribuzioni di tipo in Scala?

: _* è un'istanza speciale di ascrizione di tipo che dice al compilatore di trattare un singolo argomento di un tipo di sequenza come una sequenza di argomenti variabile, cioè varargs.

È completamente valido creare un Queueusing Queue.applyche abbia un singolo elemento che sia una sequenza o iterabile, quindi questo è esattamente ciò che accade quando dai un singolo Iterable[A].


83

Questa è una notazione speciale che dice al compilatore di passare ogni elemento come il proprio argomento, piuttosto che tutto come un singolo argomento. Vedi qui .

È un'annotazione di tipo che indica un argomento di sequenza ed è menzionata come "eccezione" alla regola generale nella sezione 4.6.2 delle specifiche del linguaggio, "Parametri ripetuti".

È utile quando una funzione accetta un numero variabile di argomenti, ad esempio una funzione come def sum(args: Int*), che può essere invocata come sum(1), sum(1,2)ecc. Se hai una lista come xs = List(1,2,3), non puoi passare xsse stessa, perché è a Listpiuttosto che un Int, ma puoi passare i suoi elementi usando sum(xs: _*).


def sum(xs: _*)genera "errore: tipo di carattere jolly non
associato

La tua risposta è chiara, ma questo in realtà sta creando più confusione per me, di solito in scala xs: intsignifica che il tipo di xs è int, passando da quella sopra una sintassi in scala dove xs: _*significa che xs è assegnato ai suoi singoli membri.
Rpant

Segue il collegamento sopra e sembra che sia così, l'ascrizione del tipo è una terminologia di scala per il casting di tipo java. Per favore correggimi se sbagliato.
Rpant

2
@ 7kemZmani: È necessario definire la funzione con un tipo specifico di VAR-args: def sum(args: Int*)e si chiama con il carattere jolly di tipo "generici" var-args: val a = sum(xs: _*). Pensa _*come "Sto passando un Int *, o una stringa *, o qualsiasi cosa * definita nella firma del metodo"
Alfonso Nishikawa

10

Per le persone di Python:

L' _*operatore di Scala è più o meno l'equivalente dell'operatore * di Python .


Esempio

Conversione dell'esempio scala dal collegamento fornito da Luigi Plinge :

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

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

a Python sarebbe simile a:

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

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

ed entrambi danno il seguente output:

Che cosa è
up
doc?


La differenza: spacchettare i parametri posizionali

Mentre l' *operatore di Python può anche occuparsi dello spacchettamento di parametri / parametri posizionali per funzioni ad arità fissa:

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

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

8

Fare lo stesso con Scala:

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

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

avrà esito negativo:

non abbastanza argomenti per il metodo moltiplicare: (x: Int, y: Int) Int.
Parametro di valore non specificato y.

Ma è possibile ottenere lo stesso con scala:

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

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

Secondo Lorrin Nelson è così che funziona:

La prima parte, f _, è la sintassi per una funzione parzialmente applicata in cui nessuno degli argomenti è stato specificato. Questo funziona come un meccanismo per ottenere una presa dell'oggetto funzione. tupled restituisce una nuova funzione quale di arity-1 che accetta una singola tupla arity-n.

Ulteriore lettura:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.