Dinamik olarak yazılmış diller tek tipli
Yazım sistemlerinin karşılaştırılması , dinamik yazmanın avantajı yoktur. Dinamik yazma, özel bir statik yazma durumudur - her değişkenin aynı türde olduğu statik olarak yazılmış bir dildir. Aynı şeyi Java'da (eksi netlik) her değişkenin türünde yaparak Object
ve "nesne" değerlerinin türünde olmasını sağlayarak yapabilirsiniz Map<String, Object>
:
void makeItBark(Object dog) {
Map<String, Object> dogMap = (Map<String, Object>) dog;
Runnable bark = (Runnable) dogMap.get("bark");
bark.run();
}
Dolayısıyla, yansıma olmadan bile, aynı etkiyi, herhangi bir statik-yazıyla yazılmış herhangi bir dilde, sözdizimsel bir kenara bırakarak elde edebilirsiniz. Ek bir ifade gücü elde edemezsiniz; tam tersine, sahip daha az bir dinamik olarak yazılan dilde değilse, çünkü ifade gücünü inkar belirli türdeki değişkenler kısıtlamak için yeteneği.
Statik olarak yazılmış bir dilde ördek havlaması yapma
Dahası, statik olarak yazılmış iyi bir dil, bir bark
işlemi olan herhangi bir türle çalışan kod yazmanıza izin verecektir . Haskell'de bu bir tür sınıfıdır:
class Barkable a where
bark :: a -> unit
Bu, bazı türlerin a
Barkable olarak kabul edilmesi için, bark
bu türün değerini alan ve hiçbir şey döndürmeyen bir işlev olması gerektiğine dair kısıtı ifade eder .
Daha sonra genel fonksiyonları fonksiyon Barkable
kısıtı olarak yazabilirsiniz :
makeItBark :: Barkable a => a -> unit
makeItBark barker = bark (barker)
Bu, gereksinimlerini makeItBark
karşılayan her türden işe yarayacağını söylüyor Barkable
. Bu benzer görünebilir interface
Java veya C # ama büyük bir avantaja sahiptir - tipleri belirtmek gerekmez ön onlar tatmin tip sınıfları. O tip söyleyebiliriz Duck
olduğunu Barkable
bile istediği zaman Duck
ben yazmadım üçüncü bir türüdür. Aslında, yazarın Duck
bir bark
işlev yazmadığı önemli değil - Duck
tatmin edici bir dil söylediğimde, gerçeği sonra sağlayabilirim Barkable
:
instance Barkable Duck where
bark d = quack (punch (d))
makeItBark (aDuck)
Bu, Duck
s havlayabildiğini ve onların kabuk işlevinin yerine getirmeden önce ördekleri yumruklayarak uygulandığını söylüyor . Bunun dışında makeItBark
ördekleri çağırabiliriz .
Standard ML
ve aynı tip sınıfı birden fazla şekilde OCaml
tatmin edebilmeniz için daha da esnektir . Bu dillerde, geleneksel sıralamayı kullanarak tamsayıların sipariş edilebildiğini söyleyebilirim ve sonra arkanı dönüp de bölünebilirlikle sıralanabilir olduklarını söyleyebilirim (örneğin , 10, 5 ile bölünebilir). Haskell'de, bir tür sınıfını yalnızca bir kez başlatabilirsiniz. (Bu, Haskell'in otomatik olarak bir ördek çağırmanın uygun olduğunu bilmesini sağlar ; SML veya OCaml'de, hangi fonksiyondan daha fazla olabileceğiniz konusunda açık olmanız gerekir .)10 > 5
bark
bark
Özlülük
Elbette, sözdizimsel farklılıklar var. Sunulan Python kodu yazdığım Java eşdeğerinden çok daha kısa. Uygulamada, bu özlü dinamik olarak yazılmış dillerin cazibesinin büyük bir parçasıdır. Ancak tür çıkarımı, statik olarak yazılmış dillerde özlediğiniz kodları yazmanıza olanak tanır, her değişkenin türünü açıkça yazmak zorunda kalmazsınız . Statik olarak yazılmış bir dil, tüm döküm ve harita manipülasyonlarının ayrıntılarını kaldırarak, dinamik yazma için yerel destek de sağlayabilir (örneğin, C # gibi dynamic
).
Doğru ama kötü yazılmış programlar
Adil olmak gerekirse, statik yazım yazım denetleyicisi doğrulayamasa da teknik olarak doğru olan bazı programları mutlaka dışlar. Örneğin:
if this_variable_is_always_true:
return "some string"
else:
return 6
Statik olarak yazılmış dillerin çoğu if
, başka bir dal asla oluşmasa da bu ifadeyi reddeder . Uygulamada hiç kimse bu tür bir kod kullanmıyor gibi görünmektedir - tip denetleyicisi için çok akıllıca olan herhangi bir şey muhtemelen kodunuzun gelecekteki yöneticilerinin sizi ve akrabalarınızı aklına getirecektir. Buna göre, birisi başarıyla 4 açık kaynaklı Python projesini Haskell'e çevirdi, bu da statik olarak yazılmış iyi bir dilin derleyemediği hiçbir şeyi yapmadıkları anlamına geliyor. Dahası, derleyici, ünitenin test edemediği birkaç tip ilişkili hata buldu.
Dinamik yazma için gördüğüm en güçlü argüman Lisp'in makroları, çünkü dilin sözdizimini keyfi bir şekilde genişletmenize izin veriyorlar. Bununla birlikte, Typed Racket , makroları olan, statik olarak yazılmış bir Lisp lehçesidir, bu yüzden statik olarak yazmak gibi görünmektedir ve makrolar aynı anda uygulanması daha zor olsa da, birbirini dışlayan değildir.
Elmalar ve Portakallar
Son olarak, dillerde sadece tür sistemlerinden daha büyük farklılıklar olduğunu unutmayın. Java 8'den önce, Java'da her türlü işlevsel programlama yapmak neredeyse imkansızdı; basit bir lambda 4 satırlık anonim sınıf kodu gerektirir. Java ayrıca, koleksiyon hazırlayıcıları için bir desteği de yoktur (örn. [1, 2, 3]
). Ayrıca takımın kalitesi ve kullanılabilirliği (IDE'ler, hata ayıklayıcılar), kütüphaneler ve topluluk desteğinde farklılıklar olabilir. Birisi Python veya Ruby'de Java'dan daha üretken olduğunu iddia ettiğinde, bu özelliğin dikkate alınmaması gerekiyor. Tüm pilleri içeren dilleri karşılaştırma , dil çekirdekleri ve tür sistemleri arasında fark var .
makeItBark(collections.namedtuple("Dog", "bark")(lambda x: "woof woof"))
. Bu argüman bir sınıf bile değil , anonim tuple adında. Ördek yazarak ("eğer böyle bir şey yaparsa ..."), esasen sıfır kısıtlama olan ve sözdizimsel yükü olmayan geçici arayüzler yapmanızı sağlar. Bunu Java gibi bir dilde yapabilirsiniz, ancak çok dağınık bir yansıma ile sonuçlanır. Java’daki bir işlev ArrayList gerektiriyorsa ve başka bir koleksiyon türü vermek istiyorsanız, SOL’sınız. Python'da bile gelemiyor.