Java 8'de işlev türlerini kaldırma nedenleri


12

JDK 8 Lambda Uzman Grubu'nun (EG) neden Java programlama diline yeni bir işlev türü eklememeye karar verdiğini anlamaya çalışıyorum.

Posta listesinin üzerinden geçerken işlev türlerinin kaldırılmasıyla ilgili tartışmayı içeren bir konu buldum .

İfadelerin çoğu benim için belirsiz olabilir, belki bağlam eksikliği ve bazı durumlarda tip sistemlerinin uygulanması hakkında sınırlı bilgim nedeniyle.

Ancak, ne anlama geldiğini daha iyi anlamama yardımcı olmak için bu sitede güvenli bir şekilde formüle edebileceğime inandığım birkaç soru var.

Posta listesindeki soruları sorabilirim, ancak konu eski ve tüm kararlar zaten verilmiş, bu yüzden her şeyden önce bu adamların planlarıyla zaten geciktiğini görerek görmezden gelineceğim.

İşlev türlerinin kaldırılmasını desteklemek ve SAM türlerinin kullanımını desteklemek için verdiği cevapta Brian Goetz şöyle diyor:

Bir şey yok. İşlev türlerinin yeniden birleştirilmesinin ne kadar yararlı olacağına dair uzun bir konu vardı. Yeniden birleşme olmadan, işlev türleri taşınır.

Bahsettiği ipliği bulamadım. Şimdi, bir yapısal fonksiyon tipinin kullanılmasının Java çoğunlukla nominal tip sistemde bazı komplikasyonları ima edebileceğini anlayabiliyorum, anlayamadığım parametreli SAM tiplerinin yeniden yapılandırma açısından nasıl farklı olduğudur.

İkisi de aynı yeniden yapılanma sorunlarına maruz kalmıyor mu? İşlev türlerinin yeniden yapılandırma açısından parametreli SAM türlerinden ne kadar farklı olduğunu anlayan var mı?

Başka bir yorumda Goetz diyor ki:

Yazmaya iki temel yaklaşım vardır: nominal ve yapısal. Bir nominal değerin kimliği, ismine dayanır; yapısal tipin kimliği, neyden oluştuğuna ("int, int" veya "int'ten float fonksiyonuna") dayanır. Çoğu dil çoğunlukla nominal veya çoğunlukla yapısal seçer; "kenarların çevresinde" dışında, nominal ve yapısal yazmayı başarıyla karıştıran pek çok dil yoktur. Java neredeyse tamamen nominaldir (birkaç istisna dışında: diziler yapısal bir türdür, ancak altta her zaman nominal bir eleman türü vardır; jeneriklerin de nominal ve yapısal bir karışımı vardır ve bu aslında birçok kaynağın bir parçasıdır. insanların jeneriklerle ilgili şikayetlerinin incelenmesi.) Java'ya yapısal bir tip sistem (fonksiyon tipleri) aşılamak ' s nominal tip sistemi yeni karmaşıklık ve uç durumlar anlamına gelir. İşlev türlerinin yararı buna değer mi?

Tip sistemlerinin uygulanmasında deneyime sahip olanlar. Burada bahsettiği bu karmaşıklıkların veya uç vakaların örneklerini biliyor musunuz?

Dürüst olmak gerekirse, tamamen JVM'ye dayanan Scala gibi bir programlama dilinin, altta yatan platformun yeniden yapılanma problemlerinde bile işlevler ve tuples gibi yapısal türleri desteklediğini düşündüğümde bu iddialarla kafam karışıyor.

Beni yanlış anlamayın, bir işlev türünün SAM türlerinden daha iyi olması gerektiğini söylemiyorum. Sadece bu kararı neden aldıklarını anlamak istiyorum.


4
"Yapısal tip bir sistemin (fonksiyon türleri) Java'nın nominal tip sistemine aşılanması yeni karmaşıklık anlamına gelir" - bu büyük olasılıkla dili kullanmak için daha fazla bilgi edinmek zorunda olan kullanıcılar için karmaşıklık anlamına geliyordu . Gibi bir şey basit ve Java kullanımı kolay C ++ öğrenmek karmaşık ve zor gibi olur böyle şeyler olurdu. Posta listesi üyeleri büyük olasılıkla önceki "büyük gelişme dalgasına" yönelik eleştirilere başvurabilir, bunun en önemli örneklerinden biri Java 5'in MyBatis'den Clinton Begin'in makalesini emmesi
gnat

3
"Basit ve kullanımı kolay Java, karmaşık ve öğrenmesi zor C ++ gibi bir şey haline gelir": Ne yazık ki, genel programlama dilleri ile ilgili bir sorun, geriye dönük uyumluluğu korumak zorunda olmaları ve bu nedenle çok karmaşık olma eğilimindedir. IMHO (hem C ++ hem de Java ile uzun yıllara dayanan deneyime sahip) bu ifade için doğru bir şey var. Sık sık Java'nın dondurulması ve bunun yerine yeni bir dil geliştirilmesi gerektiği fikrine kapılıyorum. Ancak Oracle böyle bir risk alamaz.
Giorgio

4
@edalorzo: Clojure, Groovy, Scala ve diğer dillerin gösterdiği gibi, (1) yeni bir dil tanımlamak mümkündür (2) geriye dönük uyumluluğu bozmadan zaten Java'da yazılmış tüm kitaplıkların ve araçların zenginliğini kullanmak (3) vermek Java programcıları, Java ile kalmak, başka bir dile geçmek veya her ikisini birden kullanmak isteyip istemediklerini seçme özgürlüğü sunar. IMO, mevcut bir dili süresiz olarak genişletmek, cep telefonu şirketlerinin her zaman yeni modeller oluşturması gerektiği gibi müşterileri tutmak için bir stratejidir.
Giorgio

2
Java'daki SAMbdas'tan anladığım gibi , bunun nedenlerinden biri bazı kütüphanelerin (koleksiyonların) geriye dönük olarak uyumlu kalmasının sorunlu olacağıdır .
Petr Pudlák

2
Go ile ilgili bu gönderiye bağlantı veren SO ile ilgili yazı .
assylias

Yanıtlar:


6

SAM yaklaşımı aslında Scala'nın (ve C ++ 11) anonim işlevlerle (Scala'nın =>operatörü veya C ++ 11'in []()(lambda) sözdizimi ile oluşturulan) yaptıklarına benzer .

Java tarafında cevaba ilk soru gibi bir lambda deyimi dönüş tipi yeni primitve tipte olması olup olmadığıdır intya byte, ya da bir tür bir nesne türü. Scala, var olan daha bir tam sayı sınıfının bir amacı, - ilkel türleri Int- ve işlevleri sınıfı farklı, olarak nesnelerdir Function1, Function2ve benzeri, bağımsız değişken sayısına bağlı olarak işlev alır.

C ++ 11, ruby ​​ve python benzer şekilde açık veya örtük şekilde çağrılabilen bir nesneyi döndüren lambda ifadelerine sahiptir. Döndürülen nesnenin bazı standart yöntemleri vardır (örneğin, #callişlev olarak adlandırmak için kullanılabilir. Örneğin, C ++ 11 std::functionaşırı yüklenen bir tür kullanır, operator()böylece nesnenin çağrı yönteminin çağrıları metin olarak işlev çağrıları gibi bile görünür . :-)

Java için yeni teklifin dağınık olduğu yerlerde, böyle bir yöntemin farklı bir ada sahipComparator tek bir ana yönteme sahip başka bir nesneye atanmasına izin vermek için yapısal yazım kullanılır . Bu bazı yönlerden kavramsal iğrenç olsa da, does çıkan nesne, bir geri arama, bir karşılaştırıcı temsil etmek bir nesne almak varolan işlevlere geçti ve benzeri, ve iyi tanımlanmış bir tek arama yapabilmek için bekliyoruz edilebileceğini ortalama #compareveya gibi bir yöntem #callback. C ++ 'ın geçersiz kılma hilesi, operator()C ++ 11'den önce bile bu sorunu düzgün bir şekilde atlattı, çünkü bu tür tüm geri çağrı seçenekleri aynı şekilde çağrılabilir ve bu nedenle STL, C ++ 11 lambdas'ınsortve bunun gibi. Geçmişte bu tür nesneler için standart bir adlandırma kullanmayan Java (belki de operatör aşırı yüklemesi gibi bir hile tek bir yaklaşımı açıkça göstermediği için) çok şanslı değildir, bu yüzden bu kesmek onların mevcut API'ların birçoğunu değiştirmelerini engeller .


1
İronik bir şekilde, hepsi bir çeşit "işlev benzeri şeyi" temsil eden sayısız farklı, uyumsuz türe sahip olma sorunu, kütüphaneye erken inşa etmek için gerçek işlev sözdizimine sahip olmaktan bağımsız olarak standart işlev türlerini ekleyerek düzgün bir şekilde önlenebilirdi. Bir olsaydı java.util.Function2<T1, T2, R>Java 1.0, o zaman hiçbir olmazdı Comparatoryerine bu yöntemlerin tamamı bir alacağını, arayüz Function2<T1, T2, int>. (Peki, Function2TT_int<T1, T2>ilkeller gibi arayüzlerin bir kısmı olurdu , ama benim fikrimi
anladınız
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.