Scala'da `: _ *` (kolon alt çizgi yıldızı) ne yapar?


196

Bu sorudan aşağıdaki kod parçası var :

def addChild(n: Node, newChild: Node) = n match {
  case Elem(prefix, label, attribs, scope, child @ _*) => Elem(prefix, label, attribs, scope, child ++ newChild : _*)
  case _ => error("Can only add children to elements!")
}

İçindeki her şey oldukça açık, bu parça hariç: child ++ newChild : _*

Bu ne işe yarıyor?

Bir Seq[Node]başkası ile birleştirilmiş olduğunu anlıyorum Nodeve sonra Ne yapar : _*?


70
Başlığa (kolon alt çizgi yıldızı) eklediğiniz için çok teşekkür ederim!
Gal

Yanıtlar:


151

Sekansı "uyarır" 1 .

Yapıcı imzasına bakın

new Elem(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding,
         child: Node*)

hangisi denir

new Elem(prefix, label, attributes, scope,
         child1, child2, ... childN)

ancak burada sadece bir dizi vardır , vb. yoktur child1, child2bu da sonuç dizisinin kurucuya girdi olarak kullanılmasına izin verir.

Mutlu kodlama.


1 Bunun SLS'de şirin bir adı yok, ancak ayrıntılar burada. Alınması gereken önemli şey, Scala'nın argümanları yönteme tekrarlanan parametrelerle (yukarıda belirtildiği Node*gibi) bağlama şeklini değiştirmesidir .

_*Tipi açıklama SLS "4.6.2 Tekrarlanan Parametreleri" kaplıdır.

Bir parametre bölümünün son değer parametresi “*” ile sabitlenmiş olabilir, örn. (..., x: T *). Metod içindeki bu gibi tekrarlanan bir parametrenin tipi o zaman sekans tipi scala.Seq [T] 'dir. Tekrarlanan T * parametrelerine sahip yöntemler, T tipinin değişken sayıda bağımsız değişkenini alır. Yani, (p1: T1,.., Pn: Tn, ps: S *) türünde bir yöntem m, k> = n olduğunda, bağımsız değişkenlere (e1,..., Ek) U uygulanırsa, m bu uygulamada türün (p1: T1,.., pn: Tn, ps: S,.., ps0S) U'ya sahip olması, ps'nin ötesinde herhangi bir parametre adının taze olduğu S tipi k-n oluşumları.Bu kuralın tek istisnası, son bağımsız değişkenin _ * tipi ek açıklama yoluyla bir dizi bağımsız değişkeni olarak işaretlenmiş olmasıdır. Yukarıdaki m bağımsız değişkenlere (e1,..., En, e0: _ *) uygulanırsa, o uygulamadaki m türü alınır (p1: T1,.., Pn: Tn, ps: scala) .Seq [S])


5
Aslında bir operatör olmasa da "Smooch operatörü" demeyi seviyoruz :)
Henrik Gustafsson

1
Python'da buna
ambalaj

Java varargs gibi, dizinin ne kadar uzun olabileceğine dair bir sınır var mı?
qwwqwwq

95
  • child ++ newChild - sıra
  • : - tür tanımlaması, derleyicinin anlamasına yardımcı olan bir ipucu, bu ifadenin ne tür
  • _* - herhangi bir değeri kabul eden yer tutucu + vararg operatörü

child ++ newChild : _*genişlediğinde Seq[Node]için Node*(biz yerine bir dizinin yerine bir varargs ile çalıştığınızdan derleyici söyler). Sadece varargs kabul edebilen yöntemler için özellikle yararlıdır.


1
"Yazı tipi" hakkında daha fazla bilgi verebilir misiniz? Bu nedir ve nasıl çalışır?
amorfis


24

Yukarıdaki yanıt harika görünüyor, ancak bunu açıklamak için sadece bir örneğe ihtiyacım var. İşte burada :

val x : Seq[Seq[Int]] = Seq(Seq(1),Seq(2))

def f(arg: Seq[Any]*) : Int = {
 arg.length
}
f(x) //1 as x is taken as single arg
f(x:_*)  // 2 as x is "unpacked" as a Seq[Any]*

Şimdi :_*derleyiciye ne söyleyeceğimizi biliyoruz : lütfen bu argümanı paketinden çıkarın ve x'i tek bir argüman olarak almak yerine bu elemanları fonksiyon çağrısında vararg parametresine bağlayın.

Özetle, :_*vararg parametresine argüman iletirken belirsizliği ortadan kaldırmaktır.


5

Benim gibi tembel insanlar için, sadece bir Seq varArgs dönüştürür!

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.