2015-07-05 12 views
7

yılında Neden lazy burada kullanılır?Tembellik Swift

extension SequenceType { 
    func mapSome<U>(transform: Generator.Element -> U?) -> [U] { 
     var result: [U] = [] 
     for case let x? in lazy(self).map(transform) { 
      result.append(x) 
     } 
     return result 
    } 
} 

bu uzantı, isteğe bağlı döner bir dönüşüm fonksiyonu alır ve Neden sadece self.map(transform) kullanmak nil

dönüştürülmüştür değil yalnızca değerler dizisini verir? tembellik gerekli midir?

+0

, ' (flatMap dönüşümü: Generator.Element -> u?) -> [U] 'artık Swift 2 standart kitaplığında mevcuttur :) – jtbandes

cevap

11

Bir ara ürün dizisi oluşumunu önler.

self.map(transform) 

sonra olmayan nil elemanları elde edilen dizi oluşturmak geçiyor olduğu bir tüm sekans öğeleri transformasyonu sonuçlarını içeren bir dizi döndürür.

lazy(self).map(transform) 

sonra olmayan nil elemanları almak için iterated bir dizisi transforme edilmiş elemanların vardır. Dönüştürülmüş elemanlar numaralandırma sırasında hesaplanır. (Yavaş sekansı next() her çağrı orijinal dizi sonraki elemanı dönüştürerek bir eleman oluşturur.)

Her iki yöntem de çalışır. yavaş yöntemi muhtemelen büyük dizileri için daha iyi performans gösterecektir, ancak (elemanlar bu dizi elemanları vb kopyalamak için kadar maliyetli bir değer ya da referans tipi olup, boyut dizisinin ) birçok faktöre bağlı olabilir. Küçük diziler için, tembel yöntem ek olarak ek yükünden dolayı daha yavaş olacaktır. Somut bir uygulamada, Aletlerle yapılan profilleme, hangi yöntemin kullanılacağına karar vermek için yardımcı olur.

+1

Benim (kabul edilmeyen gayri resmi) performans testleri, tembel ve tembel olmayan küçük diziler için aynı performansı gösterir, ancak bu tembel, daha büyük bir mütevazi kenar sağlar olanlar, yani buna değer (özellikle böyle bir kütüphane fonksiyonunda). İlginç bir şekilde, şu anda 2.0 aynı mantığı yapan flatMap, her ikisinden de daha kötü performans gösteriyor. –

+0

@AirspeedVelocity: Bu ilginç, geri bildirim için teşekkürler. –

+0

İlginç bir şekilde zıt sonucu aldım! Cevabımı aşağıya bakın. – Qbyte

5

de Martin R lazy() bir ara dizinin oluşumunu önler söz. Ancak, fonksiyonun yürütme süresini farklı boyutlarda karşılaştırırsam, lazy()'un "sadece"% 10 daha hızlı olduğunu görürsünüz.

lazy()lazy(), 200'den az elemanla 2 kata kadar daha hızlı dizilere sahip olduğunu ve dönüşüm olmadan işlev olarak neredeyse eşit derecede hızlı bir şekilde (% 10 daha hızlı) olduğunu görürsünüz.

((derlenmiş) kaynak dosyaları olarak bir Oyun küresel işlevleri ve protokol uzantılı Xcode 6.4 ve Xcode 7 ile test edilmiştir)

o sonlu olup olmadığını bilmiyorum Yani lazy() yerine Sequences için kullanılacak

. Sonra, döngüler için muhtemelen break veya return ile kullanılır:

for element in lazy(sequence).map{ ... } { 
    if element == 1000 { 
     break 
    } 
    // use element 
} 

da sonsuz olacağını sonsuz Sequence (gibi 1,2,3 ...) yürütme haritayı çağırırsanız. lazy() ile dönüşüm ve yürütme "gecikmeli" olur, böylece son öğeden önce döngüden ayrılırsanız "büyük" ve sonsuz dizileri daha verimli şekilde kullanabilirsiniz. Bu arada