2011-06-17 12 views
8
toplama çerçevesinin uygulanması karmaşıklığı çoğu Scala can olduğunu, aslında doğar

- C# 'ın LINQ veya diğer toplama çerçeveler aksine - yüksek mertebeden işlevleri için 'en iyi' koleksiyon türü dönmek:Can Scala koleksiyonunun seq/par/view/force, tek tip dönüş tipi prensibinin ihlali olarak görülüyor mu?

val numbers = List(1,2,3,4,5) 
numbers map (2*) // returns a List[Int] = List(2, 4, 6, 8) 

val doubles = Array(1.0, 2.0, 3.0) 
doubles filter (_ < 3) // returns Array[Double] = Array(1.0, 2.0) 

Neden bunu yapar Prensip seq, par, view, force gibi yöntemlere uymuyor mu?

numbers.view.map(2*).force 
// returns Seq[Int] = List(2, 4, 6, 8) 

numbers.seq 
// returns scala.collection.immutable.Seq[Int] = List(1, 2, 3, 4) 

doubles.par.seq 
// returns scala.collection.mutable.ArraySeq[Double] = ArraySeq(1.0, 2.0, 3.0) 

Çalışmasını engelleyen bir teknik sınırlama var mı? Yoksa tasarım/niyetle mi? LINQ temelde tembel olduğunu düşünürsek, Scala'nın eşdeğeri (view, force) daha güvenli değildir (yalnızca katı yöntemleri kullanırken), değil mi?

cevap

8

Paralel koleksiyon sınıflarına daha fazla bilgi gömmek mümkündür, böylece başlattığınız koleksiyonu geri alabilirsiniz, bu doğrudur. Bu List'u par (O (n) 'de çağırarak ve seq'u çağırdıktan sonra List'u döndükten sonra tekrar List alırsınız. Listeyi seq ile elde etmek için, tüm öğeleri vektörden tekrar listeye kopyalamanız gerekir. Yerine ne olur: a Vectorseq çağrıldığında geri dönüştürülmüş

  • ParVector alır - bu (1)
  • O size bir ParVector verecek bu vektör üzerinde tekrar par çağıran O'da dönüştürülmüş olur (1) beri vektör ve paralel vektör payı aynı temel veri

bir liste paralel koleksiyon dönüşünce yeniden yapılandırılması gerekiyor gibi bir koleksiyon, aksi üzerinde operasyonlar verimli parallelized edilemeyeceğini Bildirimi ikisi de. Bu nedenle, par ve seq numaralı çağrıları ararken kopyalama için tekrar tekrar ödeme yapmak zorunda kalmazsınız. Dönüşümler çok daha verimli hale gelir. Paralel koleksiyonların birincil amacı verimliliği arttırmak olduğundan, bu, tek tip dönüş tipi ilkesinden daha önemli görülmüştür.

+0

“Tembel”/“görünüm” den ne haber? Buna benzer problemler var mı? E. g. Vector (1,2,3) .view.map (2 *) 'niçin neden zorlanır? Seq [Int] = Vector (2, 4, 6) '? – soc

+0

Başımın üst kısmından, bunun 'map' olması gerekir - "SeqView" arkadaşı nesnesinde bulunan örtük "CanBuildFrom" çözüldüğünde tür bilgisi kaybolur. Benim tahminim, "canBuildFrom" yönteminin "ForcedCollection" türünde bir ek parametre alması ve "CanBuildFrom" - "SeqView [A, ForcedCollection]" türünün hedef türüne yerleştirilmesi ve "SeqView [A, Sekans [_]] '. Yine de işe yarayıp yaramadığını görmek için etrafta oynamamıştım. – axel22

1

Bir toplama yönteminin statik dönüş türüyle ilgili olarak, C# LINQ uzantı yöntemlerinin (Select, Where vb.) Aşırı yüklenmesini destekler ve otomatik olarak kapsamdaki en özel olanı seçer. Bu nedenle Seq.Select bir Seq, Enumerable.Select, Enumerable vb. Döndürebilir. Bu, Scala'da en belirgin örtük uygulamanın nasıl seçildiğine çok benzer.

Dinamik türle ilgili olarak, LINQ işlemleri, uzantı yöntemleri olarak uygulanır, böylece dinamik gönderim gerçekleştirilmez. Yani, (Seq as Enumerable).Select, değil, Enumerable döndürecektir. Scala'da, toplama yöntemi çağırma işlemleri dinamik olarak dağıtılır, bu nedenle dinamik tip map, filter vb. Için aynı kalır. Her iki yaklaşımın avantajları/dezavantajları vardır. Bu tür problemler için tek temiz çözüm, multimhods IMHO'dur ve hiçbir dil/çalışma zamanı bunları etkin bir şekilde desteklemez.

Çalışma zamanı davranışına gelince, LINQ her zaman koleksiyonun temkinli olarak değerlendirilmiş bir görünümünü döndürür. Görünümde, orijinal türden bir koleksiyonu döndüren yöntem yoktur; örneğin, toArray yöntemini kullanarak bir dizi oluşturmak istediğinizi belirtmeniz gerekir. IMHO, bu Scala'daki daha temiz ve daha basit bir yaklaşımdır ve tembel toplama operasyonları katı olanlardan daha iyi bir şekilde oluşturulur, ancak bu, tek bir toplama işlemi için sıkı bir koleksiyon elde etmek için ekstra bir yöntem çağrısının maliyetine varır.

+0

Bence dinamik tipteki problem, C# 'nin tip sisteminin hesaplamak için yeterince güçlü olmamasıdır. Scala ile aynı işlevselliği sağlamak, her bir koleksiyon sınıfı için her bir yöntemin doğru geri dönüş türüyle tanımlanmasını ve uygulanmasını gerektirecektir. Bu sadece C# (veya Java) 'da pratik değildir. – soc