Param: _ * Scala'da ne anlama geliyor?


87

Scala (2.9.1) 'de yeni olduğum için a'ya sahibim List[Event]ve onu a'ya kopyalamak istiyorum Queue[Event], ancak aşağıdaki Sözdizimi Queue[List[Event]]bunun yerine a değerini veriyor :

val eventQueue = Queue(events)

Bazı nedenlerden dolayı aşağıdakiler çalışır:

val eventQueue = Queue(events : _*)

Ama ne işe yaradığını ve neden işe yaradığını anlamak isterim? Queue.applyFonksiyonun imzasına zaten baktım :

def apply[A](elems: A*)

Ve ilk denemenin neden işe yaramadığını anlıyorum, ama ikincisinin anlamı nedir? Nedir :ve _*bu durumda neden applyfonksiyon sadece bir tane almıyor Iterable[A]?

Yanıtlar:


93

a: Atür tanımlamasıdır; bkz Scala'da tipi atıflara amacı nedir?

: _* derleyiciye bir dizi türündeki tek bir bağımsız değişkeni değişken bir bağımsız değişken dizisi, yani vararglar olarak işlemesini söyleyen özel bir tür tanımlaması örneğidir.

Bir yaratmak için tamamen geçerlidir Queuekullanarak Queue.applybu tek vermek ne olduğunu tam olarak bu yüzden, bu bir dizi ya iterable olan tek bir elemanı vardır Iterable[A].


83

Bu, derleyiciye her bir öğeyi tek bir argüman olarak değil, kendi argümanı olarak geçirmesini söyleyen özel bir gösterimdir. Buraya bakın .

Bu, bir sıra bağımsız değişkenini gösteren bir tür ek açıklamasıdır ve dil spesifikasyonu "Tekrarlanan Parametreler" bölüm 4.6.2'deki genel kurala bir "istisna" olarak bahsedilir.

Bir fonksiyon değişken sayıda argüman aldığında kullanışlıdır, örneğin, gibi bir fonksiyon def sum(args: Int*)olarak çağrılabilir sum(1), sum(1,2)vb. Gibi bir listeniz xs = List(1,2,3)varsa, xskendini geçemezsiniz , çünkü bu bir Listdeğil Int, ancak öğelerini kullanarak geçirebilirsiniz sum(xs: _*).


def sum(xs: _*)'error:
unbound

Cevabınız açık, ama bu aslında benim için daha fazla kafa karışıklığı yaratıyor, genellikle scala'da xs: intxs türünün int olduğu xs: _*anlamına gelir , yukarıdaki , xs'nin bireysel üyelerine dönüştürüldüğü bir scala sözdizimidir .
Rpant

Yukarıdaki bağlantıyı takip ettik ve öyle görünüyor ki, tür atama, java türü döküm için bir ölçekleme terminolojisidir. Lütfen yanlışsa düzeltin.
Rpant

2
@ 7kemZmani: Bir Belirli var-args türü ile işlevini tanımlamak zorunda: def sum(args: Int*)ve joker "jenerik" var-args türüyle diyoruz: val a = sum(xs: _*). _*"Bir Int * veya String * veya yöntem imzasında tanımlanan herhangi bir şeyi * geçiyorum" gibi düşünün
Alfonso Nishikawa

10

Python halkı için:

Scala'nın _*operatörü aşağı yukarı Python'un * operatörünün eşdeğeridir .


Misal

Dan scala örneği dönüştürme linke tarafından sağlanan Luigi Plinge :

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

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

Python'a şöyle görünür:

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

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

ve her ikisi de aşağıdaki çıktıyı verir:

Nedir
yukarı
doktor?


Fark: Konumsal parametreleri paketten çıkarma

Python'un *-operatörü, sabit uçuş fonksiyonları için konumsal parametrelerin / parametrelerin paketinin açılmasıyla da ilgilenebilir:

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

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

8

Scala ile aynı şeyi yapmak:

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

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

başaramayacak:

yöntem çarpımı için yeterli argüman yok: (x: Int, y: Int) Int.
Belirtilmemiş değer parametresi y.

Ancak aynı şeyi scala ile elde etmek mümkündür:

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

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

Lorrin Nelson'a göre şu şekilde işliyor:

İlk bölüm, f _, bağımsız değişkenlerin hiçbirinin belirtilmediği kısmen uygulanan bir işlevin sözdizimidir. Bu, işlev nesnesini elde etmek için bir mekanizma olarak çalışır. tupled, tek bir arity-n demetini alan arity-1'den yeni bir işlev döndürür.

Diğer okuma:

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.