Dinamik diller için gerçek bir avantaj var mı? [kapalı]


29

İlk önce Java'nın şimdiye kadar kullandığım tek dil olduğunu söylemek istiyorum, bu yüzden lütfen bu konudaki cehaletimi affedersiniz.

Dinamik olarak yazılmış diller, herhangi bir değişkene herhangi bir değer koymanıza izin verir. Örneğin, aşağıdaki işlevi yazabilirsiniz (psuedocode):

void makeItBark(dog){
    dog.bark();
}

Ve ne pahasına olursa olsun içinden geçebilirsiniz. Değerin bir bark()yöntemi olduğu sürece kod çalışacaktır. Aksi takdirde, bir çalışma zamanı istisnası veya benzer bir şey atılır. (Bu konuda yanılıyorsam lütfen beni düzeltin).

Görünüşe göre, bu size esneklik verir.

Ancak, dinamik diller hakkında biraz okuma yaptım ve insanların söylediği şey, dinamik bir dilde kod tasarlarken veya yazarken, tıpkı statik olarak yazılmış bir dilde yaptığınız gibi, türleri düşünün ve bunları dikkate alın.

Örneğin, makeItBark()işlevi yazarken, yalnızca 'havlayabilen şeyleri' kabul etmeyi niyet edersiniz ve yine de bu tür şeyleri yalnızca ona aktardığınızdan emin olmanız gerekir. Tek fark, şimdi derleyicinin bir hata yaptığınızda size söylemeyeceğidir.

Elbette, bu yaklaşımın bir avantajı vardır ki, statik dillerde, 'bu işlev havlayabilecek herhangi bir şeyi kabul eder' elde etmek için açık bir Barkerarabirim uygulamanız gerekir . Yine de, bu küçük bir avantaj gibi görünüyor.

Bir şey mi eksik? Dinamik olarak yazılmış bir dil kullanarak gerçekten ne kazanıyorum?


6
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.
Phoshi,

2
Bu tür bir soru daha önce sorulmuştu: burada , burada ve burada . Özellikle ilk örnek sorunuzu cevaplıyor gibi görünüyor. Belki de ayırt etmek için kendininkileri değiştirebilirsin?
logc

3
Örneğin, C ++ 'ta, herhangi bir T türüyle çalışan ve bark()bir yanlış bir şey ilettiğinizde derleyicinin şikayette bulunduğunu, ancak aslında bark () içeren bir arabirim bildirmek zorunda kalmadan şikayetçi olan bir yöntem fonksiyonunun olabileceğini unutmayın.
Wilbert,

2
@Phoshi Python'daki argüman hala belirli bir türden olmak zorunda - örneğin, sayı olamaz. Özel bir getMemberişlev aracılığıyla üyelerini alan kendi geçici nesne uygulamanız makeItBarkvarsa, dog.barkyerine çağırdığınız için patlar dog.getMember("bark"). Kodun çalışmasını sağlayan şey, herkesin Python'un yerel nesne türünü kullanmayı açıkça kabul ettiğidir.
Doval,

2
@ Phoshi Cevabımda Just because I wrote makeItBark with my own types in mind doesn't mean you can't use yours, wheras in a static language it probably /does/ mean that.belirttiğim gibi , genel olarak durum böyle değil . Java ve C # için durum budur, ancak bu diller sakat tip ve modül sistemlerine sahiptir, bu nedenle statik yazmanın ne yapabileceğini temsil etmiyorlar. makeItBarkStatik olarak yazılmış birkaç dilde mükemmel bir jenerik yazabilirim , hatta C ++ veya D gibi işlevsel olmayan diller bile yazabilirim .
Doval

Yanıtlar:


35

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 Objectve "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 barkiş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 aBarkable olarak kabul edilmesi için, barkbu 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 Barkablekısıtı olarak yazabilirsiniz :

makeItBark :: Barkable a => a -> unit
makeItBark barker = bark (barker)

Bu, gereksinimlerini makeItBarkkarşılayan her türden işe yarayacağını söylüyor Barkable. Bu benzer görünebilir interfaceJava veya C # ama büyük bir avantaja sahiptir - tipleri belirtmek gerekmez ön onlar tatmin tip sınıfları. O tip söyleyebiliriz Duckolduğunu Barkablebile istediği zaman Duckben yazmadım üçüncü bir türüdür. Aslında, yazarın Duckbir barkişlev yazmadığı önemli değil - Ducktatmin 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, Ducks 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 MLve aynı tip sınıfı birden fazla şekilde OCamltatmin 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 > 5bark 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 .


2
Kaynağınızı ilk paragrafa

2
@Matt Re: 1, önemli olmadığını farz etmedim; Conciseness altında ele aldım. Re: 2, hiçbir zaman açıkça söylemememe rağmen, "iyi" derken "tam tip çıkarımı var" ve " gerçek sonra imza yazmanız için kod eşleştirmenize izin veren bir modül sistemine sahip , Java gibi değil yukarı cephe" / C # 'nin arayüzleri. Re 3, ispat külfetinin bana, bana nasıl bir dilin sözdizimi ve özelliklere sahip iki dilin, biri dinamik olarak yazılmış, diğeri tam tip çıkarımı olan, her ikisine de eşit uzunlukta kod yazamayacağınızı açıklama konusunda .
Doval,

3
@MattFenwick Ben zaten haklı çıkardım - aynı özelliklere sahip iki dilden biri, biri dinamik olarak yazılmış ve diğeri statik olarak yazılmış, aralarındaki temel fark, tür açıklamalarının varlığı olacak ve yazım çıkarımı bunu ortadan kaldırıyor. Sözdizimindeki diğer farklılıklar yüzeyseldir ve özelliklerdeki farklılıklar karşılaştırmayı elmalar ile portakallara dönüştürür. Bu mantığın ne kadar yanlış olduğunu göstermek senin.
Doval

1
Boo'ya bir göz atmalısın. Statik olarak tür çıkarımı ile yazılmış ve dilin sözdiziminin genişletilmesine izin veren makrolar var.
Mason Wheeler

1
@Doval: Doğru. BTW, lambda notasyonu sadece işlevsel programlamada kullanılmaz: bildiğim kadarıyla, Smalltalk adsız bloklara sahiptir ve Smalltalk olabildiğince nesne yönelimlidir. Bu nedenle, çoğu zaman çözüm, adsız bir işlev veya tam bir adsız yöntemle adsız bir nesne olursa olsun, bazı parametrelerle adsız bir kod bloğunun etrafından geçmektir. Bu iki yapının temelde aynı fikri iki farklı bakış açısıyla (işlevsel ve nesne yönelimli) ifade ettiğini düşünüyorum.
Giorgio,

11

Bu zor ve oldukça öznel bir konudur. (Sorunuz görüşe dayalı olarak kapanabilir, ancak bu kötü bir soru olduğu anlamına gelmez - tam tersine, bu tür meta dil soruları hakkında düşünmek bile iyi bir işarettir - soru-cevap formatına uygun değildir. Bu forumdan.)

İşte benim görüşüme göre: Yüksek seviyeli dillerin amacı bir programcının bilgisayarla yapabileceklerini kısıtlamak . Bu, birçok insan için şaşırtıcıdır, çünkü amacın, kullanıcılara daha fazla güç vermek ve daha fazlasını elde etmek olduğuna inanırlar . Ancak Prolog, C ++ veya List'te yazdığınız her şey sonunda makine kodu olarak yürütüldüğünden, programcıya zaten montaj dilinden daha fazla güç vermek imkansızdır.

Üst düzey bir dilin amacı , programcının kendi oluşturdukları kodu daha iyi anlamalarına ve aynı şeyi yapmaları için daha verimli olmalarına yardımcı olmaktır. Bir alt rutin adı hatırlamak onaltılık bir adresten daha kolaydır. Otomatik bir argüman sayacı, buradaki bir çağrı sırasından daha kolaydır, argüman sayısını tam olarak kendi başınıza, yardım almadan almanız gerekir. Bir tür sistemi daha da ileri giderek belirli bir yerde sağlayabileceğiniz türden argümanları kısıtlar .

Burası insanların algılarının değiştiği yer. Bazı insanlar (Ben bunların arasındayım), şifrenizin rutin kontrolünün yine de tam olarak iki argüman bekleyeceği ve her zaman bir sayısal kimliği izleyen bir dize olduğu sürece, bunu kodda bildirmenin ve otomatik olarak hatırlatılmasının yararlı olacağını düşünür. daha sonra bu kurala uymayı unutursun. Derleyiciye böylesine küçük ölçekli defter tutmanın dış kaynak kullanımı, daha üst düzeydeki endişeler için zihninizi boşaltmanıza yardımcı olur ve sisteminizi tasarlama ve tasarlamada sizi daha iyi hale getirir. Bu nedenle, tip sistemleri net bir kazançtır: bilgisayarın iyi olduğu şeyi yapmasına izin verir ve insanlar da iyi olduklarını yapar.

Diğerleri oldukça farklı görüyorlar. Bir derleyici tarafından ne yapmaları gerektiğini söylemekten hoşlanmazlar. Tip bildirgesine karar vermek ve yazmak için ek çaba harcamadan hoşlanmıyorlar. Nerede kullanacağınızı tam olarak hangi tür ve argümanları kullanacağınızı söyleyen bir plan olmadan gerçek işletme kodunu yazdığınız keşifsel bir programlama stilini tercih ederler . Ve kullandıkları programlama stili için bu oldukça doğru olabilir.

Tabii ki, burada fazlasıyla sadeleştiriyorum. Tip kontrolü kesinlikle açık tip beyanlara bağlı değildir; tip çıkarımı da var. Farklı türlerde argümanlar yapan rutinlerle programlama yapmak, aksi takdirde imkansız olacak oldukça farklı ve çok güçlü şeylere izin verir, bu sadece pek çok insanın bu boşluğu başarıyla kullanacak kadar dikkatli ve tutarlı olmamasıdır.

Sonunda, bu kadar farklı dillerin hem popüler olduğu hem de ölme belirtisi göstermediği gerçeği, insanların programlamayı çok farklı bir şekilde sürdürdüğünü gösteriyor. Programlama dili özelliklerinin büyük ölçüde insan faktörleriyle ilgili olduğunu düşünüyorum - insan karar verme sürecini daha iyi destekleyen nedir - ve insanlar çok farklı çalıştıkları sürece, piyasa aynı anda çok farklı çözümler sunacaktır.


3
Cevap için teşekkürler. Bazılarının bir derleyici tarafından ne yapmaları gerektiğini söylemekten hoşlanmadıklarını söylediniz. [..] Gerçek iş kodunu tam olarak hangi tür ve argümanları kullanacağınızı size söyleyecek bir plan olmadan yazdığınız keşifsel bir programlama stilini tercih ediyorlar. ' Anlamadığım şey bu: programlama müzikal doğaçlama gibi değil. Müzik yanlış bir nota basarsanız, kulağa hoş gelebilir. Programlamada, orada olması gerekmeyen bir işleve bir şey iletirseniz, büyük olasılıkla kötü böcekler elde edersiniz. (bir sonraki yorumda devam ediyor).
Aviv Cohn,

3
Katılıyorum, ancak birçok kişi aynı fikirde değil . Ve insanlar zihinsel önyargıları konusunda oldukça elverişlidir, özellikle de onlardan haberi olmadığı için. Bu nedenle programlama stili hakkındaki tartışmalar genellikle tartışmalara veya kavgalara dönüşür ve internette rastgele yabancılarla başlamak için nadiren kullanışlıdır.
Kilian Foth

1
Bu yüzden - okuduklarıma göre - dinamik dilleri kullanan insanlar, statik dilleri kullananlar kadar türleri de dikkate alıyor. Çünkü bir işlev yazdığınızda, belirli bir tür argümanlar alması gerekiyordu. Derleyicinin bunu zorlayıp zorlamaması önemli değil. Statik yazarak size yardımcı olur ve dinamik yazarak değil. Her iki durumda da, bir fonksiyon belirli bir giriş türünü almak zorundadır. Bu yüzden dinamik yazmanın avantajının ne olduğunu göremiyorum. 'Keşif edici programlama stili' tercih etseniz bile, yine de bir işleve ne istersen geçemezsin.
Aviv Cohn,

1
İnsanlar genellikle çok farklı projelerden (özellikle büyüklükten) bahseder. Bir web sitesi için iş mantığı, tam bir ERP sistemi ile karşılaştırıldığında çok basit olacaktır. Bazı şeyleri yanlış anlama riskiniz daha düşüktür ve bazı kodları yeniden kullanabilmenin avantajı daha önemlidir. Bir veri yapısından bir Pdf (veya biraz HTML) oluşturan bir kodum olduğunu söyleyin. Şimdi farklı bir veri kaynağım var (ilk olarak bazı REST API’larından JSON, şimdi ise Excel ithalatçısı). Ruby gibi bir dilde ilk yapıyı 'taklit etmek', 'havlamak' yapmak ve Pdf kodunu yeniden kullanmak çok kolay olabilir.
thorsten müller

@Prog: Dinamik dillerin asıl avantajı, statik tip bir sistemde gerçekten zor olan şeyleri tarif etmektir. Python'daki bir işlev, örneğin, bir işlev referansı, bir lambda, bir işlev nesnesi veya tanrı olabilir, neyin hepsi neyin işe yarayacağını bilir. Başka bir nesneyi saran ve sıfır sözdizimsel ek yükü olan yöntemleri otomatik olarak gönderen bir nesne oluşturabilirsiniz ve her işlev esasen sihirli bir şekilde parametreleştirilmiş tiplere sahiptir. Dinamik diller işleri hızlıca halletmek için harikadır.
Phoshi

5

Dinamik diller kullanılarak yazılmış kod, statik tip bir sisteme bağlanmaz. Bu nedenle, bu birleştirme eksikliği, zayıf / yetersiz statik tip sistemlere kıyasla bir avantajdır (bununla birlikte, büyük bir statik tip sisteme kıyasla bir yıkama veya dezavantaj olabilir).

Ayrıca, dinamik bir dil için, statik tip bir sistemin tasarlanması, uygulanması, test edilmesi ve bakımı gerekmez. Bu, uygulamayı statik tip sistemli bir dile kıyasla daha kolaylaştırabilir.


2
İnsanlar sonunda temel bir statik tip sistemi birim testleri ile tekrar uygulama eğiliminde değiller mi (iyi bir test kapsamı hedef alırken)?
Den

Ayrıca burada "eşleştirme" ile ne demek istiyorsunuz? Örneğin mikro hizmetler mimarisinde nasıl tezahür eder?
Den

@Den 1) iyi bir soru, bunun OP ve cevabımın kapsamı dışında olduğunu hissediyorum. 2) Bu anlamda eşleştirmeyi kastediyorum ; kısaca, farklı tip sistemler bu dilde yazılmış kod üzerinde farklı (uyumsuz) kısıtlamalar getirir. Üzgünüm, son soruyu cevaplayamıyorum - bu konuda mikro hizmetler hakkında neyin özel olduğunu anlamıyorum.

2
@Den: Çok iyi nokta: Bir derleyici tarafından statik olarak yazılmış bir dilde yakalanacak Python kapak hatalarında yazdığım birim testlerinin sık sık olduğunu gözlemliyorum.
Giorgio

@MattFenwick: “Dinamik bir dil için statik tip bir sistemin tasarlanması, uygulanması, test edilmesi ve bakımı yapılmaması” avantajını yazdınız. Den, sık sık türlerinizi doğrudan kodunuzda tasarlamak ve test etmek zorunda olduğunuzu gözlemledi. Bu nedenle çaba kaldırılmaz ancak dil tasarımından uygulama koduna taşınır.
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.