C #, Java ve Scala'nın Kapaklar / Lambdas /… yaklaşımlarındaki avantaj ve dezavantajları nelerdir?


30

Ben C # ve Scala arasındaki teknik uygulama farklılıkları ve her iki çözümler uygulama fikirleri ve e-posta içinde dile endişeleri nasıl karşılaştırılacağı merak ediyorum Peek Geçmiş lambda Brian Goetz tarafından, posta listesine gönderilen Proje Lambda'ya (JSR 335) ?

E-postadan:

"Belki de lambdalar sadece iç sınıf örnekleri olmalı, bu gerçekten basit olurdu" yolunu araştırdık, ama sonunda "fonksiyonlar dilin geleceği için daha iyi bir yön" konumuna geldi.

ve Ötesi:

Dünyanın lambda objeleri görüşü, bu olası gelecekle çelişiyor. Dünyadaki lambda-işlevler görüşü değildir ve bu esnekliği korumak, nesnelerin görünümünde bile lambdaların yüklenmemesinden yana olan noktalardan biridir.

Sonuç:

Lambdas fonksiyonlar kapıları açar. Lambdas-are-nesneler onları kapatır.
Bu kapıların açık kaldığını görmeyi tercih ediyoruz.

Reddit iş parçasındaki bir kişiden bazı yorumlar şöyle diyor:

Aslında bu konuda Neal Gafter'e e-posta ile yolladım ve C # ve onun şu anki Java tasarımına ilişkin sınırlı anlayışına, delegelerin aslında işlev türleri değil de nesneler olduğu için oldukça benzer. Java'nın, C # 'nın lambdalarının dezavantajlarından ders alması ve bunlardan kaçınması gerektiğine inanıyor gibi gözüküyor (tıpkı Java'nın dezavantajlarından öğrenilen ve başlangıçta onlardan kaçındığı gibi).

Neden "Lambdas-işlevler" yaklaşımı gelecekte "Lambdas-nesneler" den daha fazla fırsat sağlıyor? Birisi hangi farklılıkların olduğunu ve kodun nasıl yazılacağını nasıl etkileyeceğini açıklayabilir mi?

Scala'daki şeylerin sadece işe yaradığını görünce, C # / Java'da (8) önerilen / önerilen yaklaşımlarla ilgili bir şeyleri özlediğimi düşünüyorum, muhtemelen geriye dönük uyumluluk ile ilgili endişelerle mi ilgili?


1
Bu ilginç. Javas tipi sistemin şu an için bir fonksiyon kavramı olmadığı göz önüne alındığında, bunun önce bunu tanıtması gerektiği anlamına geliyor. Dilin bununla çok karmaşık hale gelmesi mümkün olabilirdi.
Ingo

İşlevler, bazı arabirimlerin örnekleri olmamalıdır mı? Onlarda özel olan ne?
soc,

Lisp / Scheme / Clojure nesneleri modelleyebilir, Java / C # ise fonksiyonların keyfi yerleştirilmesini modelleyemez. Ancak Python her iki dünyanın da en iyisine sahip görünüyor.
İş

Yanıtlar:


15

Nesnelere karşı fonksiyonlarla ilgili tartışmanın kırmızı bir ringa balığı olduğunu düşünüyorum. Soru ise, "Bir lambda bir işlev mi yoksa bir nesne midir?" Cevap evet olmalı .

Birinci sınıf fonksiyonların amacı budur: başka tiplerden farklı olarak ele alınmazlar. Java zaten Nesne ve ilkel tipler arasındaki farkları görmezden gelmeyi başarır (ve Scala daha da iyidir), yani bir lambda Nesne'nin bir alt sınıfı mı yoksa yeni bir ilkel tip mi yoksa başka bir şey mi dil için önemli değil. Önemli olan, lambdalarınızı koleksiyonlara koyabileceğiniz, aranmak için dolaştırabileceğiniz, arayabileceğiniz ve bir nesne ya da yöntemle yapmak isteyebileceğiniz başka bir şey yapabileceğinizdir.

Scala bunu, çağrılabilir bir yöntem applyolan ve yalnızca ()yöntem çağrısı gibi görünmesini sağlayan çağrılabilir bir nesne kullanarak gerçekleştirir . Bu muhteşem çalışıyor; çoğu zaman bir yöntemin olup olmadığına veya bir işlev nesnesinin uygulamasını çağırdığına bile bakmana gerek yok.


9

Anladığım kadarıyla, lambdaların birincil dil düzeyinde nasıl değerlendirildiği hakkında daha fazla şey . E-postanın dediği gibi

Mevcut tasarımın lambda - SAM tipleri - için onları etkin bir şekilde obje yapmak için bir obje kutusuna sıkı bir şekilde bağlı olduğunu düşünebilirsiniz. Ancak, gelecekte 'çıplak' lambdaları düşünmemizi veya lambdalar için diğer dönüşüm bağlamlarını düşünmemizi veya lambdaları kontrol yapılarına daha sıkı bir şekilde entegre etmemizi sağlamak için yüzey alanından dikkatlice gizlenmiştir. Bunu şimdi yapmıyoruz ve bunu yapmak için somut bir planımız bile yok, ancak gelecekte bunu yapmamız muhtemelen tasarımın kritik bir parçası.

Bence bu, sorunuzu oldukça iyi bir şekilde özetliyor. Eğer "lambdas nesnelerdir" diye ilan ederseniz, o zaman onlar sadece belirli bir sınıfın nesnesidir ve bununla sıkışıp kalıyorsunuz. Öte yandan, "lambdas fonksiyon" ilan ederseniz, anlamsal olarak daha zengin bir oyun alanına sahip olursunuz. Java 1.7 onları nesnelere indirgeyebilir, bu yüzden neredeyse bu noktada özdeştirler.

Ancak Java 1.8 veya 1.9, işlevlerin çok daha esnek bir şekilde kullanılmasını sağlamak yerine, dilde (birleştirilmiş yapısal türler gibi) değişiklikler getirebilir. Eğer "lambda nesneler" olsaydı, bu değişiklikler geriye dönük olarak uyumlu olmazdı ve insanların mevcut kodlarını kırmamak için yeni bir konsept ortaya koymak zorunda kalacaktınız. Ama eğer javacsessizce sessizce sahne arkasındaki nesnelere lambdalar dönüştürüyor olsaydı , yeni javac, anlambilim hala devam ettiği sürece onları istediği her şeye dönüştürebilirdi.


C #! 'daki lamdalar = delegelerden. Derleyici, onları meşe ağaçlarına veya İfade ağaçlarına derleme seçeneğine sahiptir. hem gerçekten nesne grafikleri vardır ama bunlar için derlenmiş değildir bir "Özellikle sınıfın" ne de belirli bir miras ağacın bile bir sınıf
Rune FS

Eğer doğru anlarsam, lambda'yı nesneyle ilişkilendiren nesnenin bir iç sınıfına derlemek, eğer gelecekte Java yüksek dereceli işlevler (aynı nesne seviyesindeki işlevler) eklemek zorunda kalırsanız, sınıf içi uygulamayı kullanamadım ve bir tutarsızlık olacaktı. Java'nın yakın zamanda daha üst düzey işlevlere sahip olacağını sanmıyorum.
mwolfetech

@mwolfetech: Bildiğim kadarıyla, zaten savunucu yöntemlerle Java 8 için planlanmışlar. Onlar gibi şeyler eklemek istiyorum foreach, map, filterkoleksiyonlarına.
soc,

@soc İyi nokta, JSR sayısına ve gerçekte tamamlayıp tamamlamayacaklarını ve JDK'nın hedef versiyonunu yapmayı zorlaştırmak zor. Defender yöntemleri aynı JSR'nin bir parçası olabilir gibi gözüküyor. Bu JSR ile ilgili olarak , Brian Goetz’in Lambda Devleti’ndeki görevini faydalı buldum - SAM türlerini ve lambda ifadelerinin uygulanması için mevcut düşünceleri açıklıyor.
mwolfetech

"güncel düşünceler" mhhh, 2010'dan bu yazı artık kullanılmıyor mu?
soc,

5

Çoğunlukla, bir şeye çok erken bakmak istemiyor. Sunulan silme dışında bir sebep göremiyorum, ama bu gerçekten çok güçlü bir sebep.

İşlev türlerini sevmiyorum - işlev türlerini seviyorum - ancak bu işlev türleri Java tür sisteminin mevcut bir yönü ile kötü bir şekilde mücadele etti, silme. Silinen işlev türleri her iki dünyanın da en kötüsüdür.

Scala'daki bu yöntemleri göz önünde bulundurun Regex:

def replaceAllIn (target: CharSequence, replacer: (Match)  String): String
def replaceSomeIn (target: CharSequence, replacer: (Match)  Option[String]): String

Basitçe bunlar olsaydı daha basit olurdu:

def replace (target: CharSequence, replacer: (Match)  String): String
def replace (target: CharSequence, replacer: (Match)  Option[String]): String

Maalesef bu mümkün değil, çünkü bu iki işlev silme altında aynı . Ancak, tamam, bu işlev biraz farklı şeyler yapar, bu nedenle farklı bir ad yeterince adil olabilir.

Bununla birlikte, a Matchçok faydalı bir şeydir, ancak çoğu zaman eşleşmesini Stringveya alt grupların listesini istediğiniz zaman alırsınız . Şunlara sahip olmak istiyoruz:

def replaceAllIn (target: CharSequence, replacer: (String)  String): String
def replaceAllIn (target: CharSequence, replacer: (Seq[String])  String): String
def replaceAllIn (target: CharSequence, replacer: (Match)  String): String

Silme nedeniyle mümkün değil. Bu özel örneği seçtim çünkü doğrudan bununla ilgilendim, ancak insanların bu aşırı sorunun neden bir aşırı yükün neden yasadışı olduğunu sorduğu Stack Overflow hakkında en az yarım düzine soru gördüm.

Ve sonra, Scala'nın desen eşleşmesinin ve instanceofJava'ların silme nedeniyle etkili bir şekilde işe yaramaz olduğunu düşünün .

İşlev türlerini bu konuyla ilgilenene kadar ertelemenin adil olacağını düşünüyorum. Ne de olsa, JVM'de bolca dil var ve Java'nın hızlı gelişen bir dil değil.


Tip silme, sahip oldukları tek problemse, ne yapmayı planlıyorlar? Bu gezegendeki her kodu kırmak, Java 5 için şimdiden bir seçenek değildi ...
soc

@soc Çok memnunum ben ayakkabılarında değilim! Ama bu Sun'dı, bu Oracle. Oracle, ana ürününün büyük ve hatta küçük sürümleri arasında kırılma değişiklikleri yapma konusunda hiçbir zaman bir denklem yaşamamıştı.
Daniel C. Sobral,

Belki de dilin adını değiştirmeli ve geriye dönük uyumluluktan düşerek yeni bir dil geliştirmeye başlamalıdırlar. Böylece, eski ve sağlam bir dille oynamaya gerek kalmadan yeni bir dilin faydaları olur. Sonuçta, Scala ve Clojure'in yaptığı şey bu.
Giorgio

@ Giorgio Bu biraz anlamsız olurdu. Dediğin gibi Eh, Java bugünkü sorumludur insanların bazıları, o yaptı, ama orada olan alternatifler. Ancak Java'dan sorumlu insanlar , Java'nın kendisini geliştirmesi gerekir - sonuçta, bundan sorumludurlar . Tek alternatif basitçe Java'yı bırakmak ve onu kontrol etmekten kaynaklanan tüm faydalardan vazgeçmek.
Daniel C. Sobral

@Dieliel C. Sobral: IMO bir programlama dili bir yazılım parçasına benziyor: başlangıçta temiz ve iyi bir tasarım olabilir, ancak ne kadar çok oynarsanız o kadar çok karışıklaşır. Bu yüzden, geliştiricilerin Java'yı bir dil olarak dondurup geliştirmeye, (1) yeni kütüphaneler yaratmaya veya var olanları geliştirmeye, (2) JVM'yi (mümkünse), (3) yeni diller geliştirmeye yoğunlaştıracağını düşünüyorum. . Ancak dediğiniz gibi, Java'dan sorumlu olan ve yükseltmeleri satmaya devam etmek isteyen insanlar var. Bu yüzden onu "serin" tutmak için uzatacaklar. Sadece 2 sentim.
Giorgio,
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.