Neden dinamik olarak yazılan diller geliştiricinin türü belirtmesine izin vermiyor?


14

Bildiğim dinamik olarak yazılan diller, geliştiricilerin değişken türlerini belirtmesine asla izin vermez veya en azından bunun için çok sınırlı bir desteğe sahip değildir.

Örneğin JavaScript, uygun olduğunda değişken türlerini zorunlu kılmak için herhangi bir mekanizma sağlamaz. PHP yöntemi, argümanların bazı türlerini belirtmenizi sağlar fakat yerli türleri (kullanmak yolu yoktur int, stringbağımsız değişkenler için, vb) ve argümanlar dışında herhangi türlerini uygulamak için bir yolu yoktur.

Aynı zamanda, bazı durumlarda tür kontrolünü manuel olarak yapmak yerine, dinamik olarak yazılan bir dilde bir değişkenin türünü belirleme seçeneğine sahip olmak uygun olacaktır.

Neden böyle bir sınırlama var? Teknik / performans nedenlerinden ötürü (JavaScript durumunda olduğunu varsayalım) mı yoksa sadece siyasi nedenlerden dolayı mı (PHP'nin durumu olduğuna inanıyorum)? Bu, aşina olmadığım dinamik olarak yazılmış diğer diller için geçerli mi?


Düzenleme: cevapları ve yorumları takip ederek, bir açıklama örneği: diyelim ki düz PHP'de aşağıdaki yöntem var:

public function CreateProduct($name, $description, $price, $quantity)
{
    // Check the arguments.
    if (!is_string($name)) throw new Exception('The name argument is expected to be a string.');
    if (!is_string($description)) throw new Exception('The description argument is expected to be a string.');
    if (!is_float($price) || is_double($price)) throw new Exception('The price argument is expected to be a float or a double.');
    if (!is_int($quantity)) throw new Exception('The quantity argument is expected to be an integer.');

    if (!$name) throw new Exception('The name argument cannot be an empty string.');
    if ($price <= 0) throw new Exception('The price argument cannot be less or equal to zero.');
    if ($price < 0) throw new Exception('The price argument cannot be less than zero.');

    // We can finally begin to write the actual code.
    // TODO: Implement the method here.
}

Bazı çabalarla bu yeniden yazılabilir ( PHP'deki Sözleşmelerle programlama bölümüne bakınız ):

public function CreateProduct($name, $description, $price, $quantity)
{
    Component::CheckArguments(__FILE__, __LINE__, array(
        'name' => array('value' => $name, 'type' => VTYPE_STRING),
        'description' => array('value' => $description, 'type' => VTYPE_STRING),
        'price' => array('value' => $price, 'type' => VTYPE_FLOAT_OR_DOUBLE),
        'quantity' => array('value' => $quantity, 'type' => VTYPE_INT)
    ));

    if (!$name) throw new Exception('The name argument cannot be an empty string.');
    if ($price <= 0) throw new Exception('The price argument cannot be less or equal to zero.');
    if ($price < 0) throw new Exception('The price argument cannot be less than zero.');

    // We can finally begin to write the actual code.
    // TODO: Implement the method here.
}

Ancak, PHP isteğe bağlı olarak bağımsız değişkenler için yerel türleri kabul ederse aynı yöntem aşağıdaki gibi yazılır:

public function CreateProduct(string $name, string $description, double $price, int $quantity)
{
    // Check the arguments.
    if (!$name) throw new Exception('The name argument cannot be an empty string.');
    if ($price <= 0) throw new Exception('The price argument cannot be less or equal to zero.');
    if ($price < 0) throw new Exception('The price argument cannot be less than zero.');

    // We can finally begin to write the actual code.
    // TODO: Implement the method here.
}

Hangisi yazmak daha kısa? Hangisini okumak daha kolay?


1
İsteğe bağlı olarak, dinamik olarak yazılan bazı dillerdeki türleri belirtebilirsiniz - örneğin, Ortak Lisp.
SK-mantığı

Oldukça dinamik olarak yazılmış birkaç dil, bir türü zorlamak için dökümler kullanır ...
Trezoid

Bazıları yapar. Örneğin Objective-C dinamik olarak yazılmıştır, ancak değişkenler için bir tür bildirebilirsiniz ve beklediğiniz türü alamazsanız derleyici uyarı verir.
mipadi

1
Clojure normalde dinamik olarak yazılan bir dile örnektir, ancak isteğe bağlı olarak "tip ipuçları" aracılığıyla değişken türleri verebilirsiniz (bu genellikle derleme zamanı türü bilgilerinin performans avantajlarından yararlanmak için gerektiğinde yapılır)
mikera

1
Groovy, bir türün belirtilmesine izin veren dinamik olarak yazılan bir dile başka bir örnektir.
Eric Wilson

Yanıtlar:


17

Statik yazmanın olması, programınızın türler açısından doğru olduğunu statik olarak kanıtlama yeteneğidir (not: her anlamda tamamen doğru değildir). Boyunca statik bir tip sisteminiz varsa, çoğu zaman tip hatalarını tespit edebilirsiniz.

Yalnızca kısmi tür bilginiz varsa, arama grafiğinin yalnızca tür bilgisinin tamamlandığı küçük parçalarını kontrol edebilirsiniz. Ancak eksik parçalar için size yardımcı olamayacağı, ancak yanlış bir güvenlik hissi verebileceği tip bilgilerini belirtmek için zaman ve çaba harcadınız.

Tip bilgisini ifade etmek için, dilin aşırı derecede basit olamayacak bir kısmına ihtiyacınız vardır. Yakında böyle bilgilerin intyeterli olmadığını göreceksiniz ; List<Pair<Int, String>>parametrik türler, vb. gibi bir şey isteyeceksiniz . Java'nın oldukça basit durumunda bile yeterince kafa karıştırıcı olabilir.

Daha sonra, çeviri aşamasında ve yürütme aşamasında bu bilgileri kullanmanız gerekir , çünkü yalnızca statik hataları kontrol etmek saçmadır; kullanıcı, tür kısıtlamalarının belirtilirse her zaman beklemesini bekler. Dinamik diller oldukları kadar hızlı değildir ve bu tür denetimler performansı daha da yavaşlatır. Statik bir dil, türleri kontrol etmek için ciddi çaba harcayabilir, çünkü bunu yalnızca bir kez yapar; dinamik bir dil yapamaz.

Şimdi, tüm bunları eklediğinizi ve koruduğunuzu düşünün, böylece insanlar bazen isteğe bağlı olarak bu özellikleri kullandı, yalnızca küçük bir hata türünü tespit etti. Ben çabaya değeceğini sanmıyorum.

Dinamik dillerin asıl noktası, statik bir dilde yapıldığında çok daha fazla şey içeren şeyleri kolayca yapabileceğiniz çok küçük ve çok biçimlendirilebilir bir çerçeveye sahip olmaktır: metaprogramlama, alay ve test, kodun dinamik olarak değiştirilmesi, vb. Her ikisi de çok dinamik olan Smalltalk ve Lisp, onu kaynaktan inşa etmek yerine çevre görüntülerini göndermek gibi bir aşırıya götürdü. Ancak, belirli veri yollarının tür açısından güvenli olduğundan emin olmak istediğinizde, iddia ekleyin ve daha fazla birim testi yazın.


1
+1 olsa da, testler yalnızca belirli durumlarda hataların meydana gelmediğini gösterebilir. (Tür) hatalarının imkansız olduğuna dair bir kanıtın yerine geçmezler.
Ingo

1
@Ingo: kesinlikle. Ancak dinamik diller, nispeten basit fikirleri çok hızlı ifade ettiğiniz tinkering ve hızlı prototipleme için mükemmeldir. Kurşun geçirmez üretim kodu istiyorsanız, bazı kararlı çekirdek bileşenleri çıkardıktan sonra daha sonra statik bir dile dönebilirsiniz.
9000

1
@ 9000'de harika olduklarından şüphe duymuyorum. Sadece 3 veya 4 topal test yazmanın olmadığını ve tip güvenliğini sağlayamayacağını belirtmek istedim .
Ingo

2
@ 9000, Doğru ve kötü haber o zaman bile, neredeyse imkansız. Haskell veya Agda kodu bile, örneğin çalışma zamanında kullanılan kütüphanenin doğru olduğu varsayımlarına dayanır. Bununla birlikte, bazı düzinelerce kaynak kodu dosyasına yayılmış 1000 LOC olan bir projede, bir şeyi değiştirebildiğinizde çok havalı ve derleyicinin değişikliğin bir etkisi olduğu her satırı göstereceğini biliyorsunuz.
Ingo

4
Kötü yazılmış testler statik tip kontrolünün yerini tutmaz: daha düşüktür. İyi yazılmış testler de statik tip kontrolünün yerini tutmaz: üstündür.
Rein Henrichs

8

Çoğu dinamik dilde, bir nesnenin veya değerin türünü en azından dinamik olarak test edebilirsiniz .

Ve bazı dinamik diller için statik tip çıkarımlar, denetleyiciler ve / veya uygulayıcılar vardır: ör.

Ve Perl 6, statik yazı ile isteğe bağlı bir tip sistemi destekleyecektir .


Ama alt çizgi bir sürü insan dinamik dilleri kullanan olduğunu tahmin çünkü onlar dinamik yazıldığında ve onlar için isteğe bağlı statik yazarak çok "ho hum" dir. Ve diğer birçok insan bunları kullanıyor çünkü büyük ölçüde affedici doğa dinamik yazımının bir sonucu olarak "programcı olmayanlar için kullanımı kolay". Onlar için, isteğe bağlı yazma ya anlamayacakları ya da kullanmak için uğraşmayacakları bir şeydir.

Alaycı olsaydınız, isteğe bağlı statik yazmanın her iki dünyanın en kötüsünü sunduğunu söyleyebilirsiniz. Statik bir tür zealot için, tüm dinamik tür hatalarını önlemez . Dinamik tip bir fan için, hala düz bir ceket ... kayışlar sıkıca yapılmasa da.


2
Tipleri kendiniz kontrol etmenin çoğu durumda çoğu topluluk tarafından kaşlarını çattığına dikkat edilmelidir. Nesne hiyerarşileriyle uğraşırken polimorfizm (özellikle "ördek tiplendirme") kullanın, mümkünse / mantıklıysa beklenen türe zorlayın. Birkaç durum, herhangi bir türe izin vermenin mantıklı olmadığı yerlerde kalır, ancak birçok dilde bu vakaların çoğunda zaten bir istisna alırsınız, bu nedenle tür denetimi nadiren yararlıdır.

4
"insanlar genellikle dinamik olarak yazıldıkları için dinamik olarak dil kullanırlar" : JavaScript kullanılır, çünkü çoğu tarayıcı tarafından desteklenen tek dildir. PHP popüler olduğu için kullanılır.
Arseni Mourzenko

2

Javascript bazı isteğe bağlı statik yazmayı planladı ve birçok olgun dinamik dil bu yöne gidiyor gibi görünüyor.

Bunun nedeni, ilk kodlama yaptığınızda hızlı ve dinamik olarak yazılmak istemenizdir. Kodunuz sağlam, çalışır ve birçok kullanım (r) s olduğunda, hataları azaltmak için tasarımı kilitlemek istersiniz. (bu hem kullanıcılar hem de geliştiriciler için faydalıdır, çünkü birincisi aramalarını kontrol ederken hata alır ve ikincisi yanlışlıkla işleri bozmaz.

Benim için bir anlam ifade ediyor, çünkü genellikle bir projenin başlangıcında çok fazla tür denetimi buluyorum, hangi dili kullanırsam kullansam da, ömrünün sonunda çok az;).


JavaScript'te isteğe bağlı statik yazmayı dahil etmek için bu planları bilmiyorum; ancak umarım ActiveScript'teki kadar acımasız olmamışlardır. JavaScript ve Java'nın en kötüsü.
Javier

JS 4 (veya ECMAscript 4) için planlandı, ancak bu sürüm tartışma nedeniyle düştü. Eminim benzer bir şey gelecekte, bazı dillerde görünecektir. (Python'da bunu dekoratörler ile yapabilirsin, btw.)
Macke

1
Dekoratörler dinamik tür denetimi, bir tür iddia ekler . Dilin aşırı dinamizmi nedeniyle Python'da kapsamlı statik tip denetimi alamazsınız.
9000

@ 9000: Doğru. Bununla birlikte, dinamik tip kontrolünün kötü olduğunu düşünmüyorum (ancak ördek tipi karşılaştırmaları ala JS4 tercih ederim), özellikle birim testlerle birleştirildiğinde ve dekoratörleri tanımlamak daha yararlı olabilir. standardize.
Macke

tabii ki kötü değil! Bu bir ahlak meselesi değil. Bir noktada, tür şu veya bu şekilde "kontrol edilmelidir". C'ye * ((double *) 0x98765E) yazarsanız, CPU bunu yapar ve 0x98765E'nin gerçekten bir çifte işaretçi olup olmadığını kontrol eder.
Ingo

2

Python nesneleri yapmak bir türü var.

Nesneyi oluştururken türü belirtirsiniz.

Aynı zamanda, bazı durumlarda tür kontrolünü manuel olarak yapmak yerine, dinamik olarak yazılan bir dilde bir değişkenin türünü belirleme seçeneğine sahip olmak uygun olacaktır.

Aslında, Python'da manuel tip kontrolü neredeyse her zaman zaman ve kod kaybıdır.

Python'da tip kontrol kodu yazmak sadece kötü bir uygulamadır.

Uygunsuz bir tür bazı zararlı sosyopatlar tarafından kullanılmışsa, Python'un sıradan yöntemleri, tür uygun olmadığında sıradan bir istisna oluşturacaktır.

Kod yazmazsınız, programınız hala bir ile başarısız olur TypeError.

Çalışma zamanında türü belirlemeniz gereken çok nadir durumlar vardır.

Neden böyle bir sınırlama var?

Bu bir "sınırlama" olmadığından, soru gerçek bir soru değildir.


2
"Python nesnelerinin bir türü var." - ohh gerçekten mi? Tıpkı perl nesneleri, PHP nesneleri ve dünyadaki diğer tüm veri öğeleri gibi. Statik ve dinamik yazım arasındaki fark yalnızca tür denetlenecekse, yani tür hataları kendilerini gösterdiğinde ortaya çıkar. Derleyici hataları olarak görünüyorlarsa, statik yazımdır, çalışma zamanı hataları olarak görünüyorlarsa dinamiktir.
Ingo

@Ingo: Açıklama için teşekkürler. Sorun, C ++ ve Java nesnelerinin bir türden diğerine dökülebilmesi, bir nesnenin türünü biraz bulanık hale getirmesi ve bu nedenle bu derleyicilerdeki "tür kontrolünü" biraz bulanıklaştırmasıdır. Python tipi kontrolün - çalışma zamanında olsa bile - çok daha az bulanık. Ayrıca, soru, dinamik olarak yazılan dillerin türleri olmadığını söylemeye çok yakın çalışır. İyi haber şu ki, bu ortak hatayı yapmıyor.
S.Lott

1
Haklısınız, tür çevirmeleri (tür dönüşümlerinin aksine, yani ((çift) 42)) statik yazmayı ters çevirin. Tip sistemi yeterince güçlü olmadığında bunlara ihtiyaç vardır. Java 5'ten önce, Java'nın parametrelenmiş türü yoktu, o zaman tür dökümü olmadan yaşayamazsınız. Bugün çok daha iyi, ancak tip sistemi, daha yüksek dereceli polimorfizmden bahsetmemek için hala daha yüksek türlerden yoksundur. Dinamik olarak yazılan dillerin çok fazla takipçiden zevk almasının mümkün olduğunu düşünüyorum çünkü çok dar tip sistemlerden birini özgürleştiriyorlar.
Ingo

2

Çoğu zaman, en azından önerdiğiniz ayrıntı düzeyinde olmanıza gerek yoktur. PHP'de kullandığınız operatörler, argümanların ne olmasını beklediğinizi mükemmel bir şekilde netleştirir; bir dizeyi bekleyen bir işleme geçirdiğinizde bile PHP mümkün olduğunda değerlerinizi yayınlasa da tasarımın gözetimi biraz fazladır ve oyuncu kadrosu her zaman anlamlı olmadığı için bazen garip sonuçlar elde edersiniz ( tip kontrolleri nerede ve bu tam olarak vardır faydalıdır). Bunun dışında, tamsayılar 1ve / 5veya dizeler eklemeniz fark etmez "1"ve "5"- yalnızca+operatörü, argümanlara sayı olarak davranmak istediğinizi PHP'ye bildirir ve PHP itaat eder. İlginç bir durum, MySQL'den sorgu sonuçları aldığınızda: Birçok sayısal değer dizeler olarak döndürülür, ancak sayı olarak kabul ettiğinizde PHP bunları sizin için yayınladığından fark etmezsiniz.

Python, türleri hakkında biraz daha katıdır, ancak PHP'den farklı olarak, Python en başından istisnalara sahiptir ve sürekli olarak kullanır. "İzin vermekten daha kolay affetmek" paradigması, işlemi yalnızca tür denetimi yapmadan gerçekleştirmenizi ve türler mantıklı olmadığında ortaya çıkan bir istisnaya güvenmenizi önerir. Düşünebileceğim tek dezavantajı, bazen, bir türün olmasını beklediğinizle eşleşmediğini, ancak sebebini bulmak sıkıcı olabileceğini göreceksiniz.

Dinamik diller yoktur: Ve düşünün başka bir nedeni var olması bir derleme aşamasını. Tür kısıtlamalarınız olsa bile, derleme zamanı olmadığı için yalnızca çalışma zamanında tetiklenebilirler . Çekleriniz zaten çalışma zamanı hatalarına yol açarsa, bunları uygun şekilde modellemek çok daha kolaydır: Açık denetimler ( is_XXX()PHP veya typeofjavascript'te olduğu gibi) veya istisnalar (Python'un yaptığı gibi) atarak. İşlevsel olarak, aynı etkiye sahipsiniz (bir tür denetimi başarısız olduğunda çalışma zamanında bir hata sinyali verilir), ancak dilin diğer anlamlarıyla daha iyi bütünleşir. Tip hatalarını dinamik bir dilde diğer çalışma zamanı hatalarından temel olarak farklı bir şekilde ele almak mantıklı değildir.


0

Haskell ilginizi çekebilir - bu tür sistem kod türlerini ihlal eder ve türleri de belirtebilirsiniz.


5
Haskell harika bir dildir. Dinamik dillerin bir şekilde tersidir: türleri tanımlamak için çok zaman harcarsınız ve genellikle türlerinizi anladıktan sonra program çalışır :)
9000

@ 9000: Gerçekten. Derlendiğinde, genellikle çalışır. :)
Macke

@Macke - farklı değerleri için genellikle elbette. :-) Benim için, yazı sisteminin ve fonksiyonel paradigmanın en büyük yararı, başka bir yerde işaret ettiğim gibi, bir yerde bir değişikliğin sessizce başka bir yere bağlı bazı kodları etkileyip etkilemediğini umursamayacağıdır - derleyici tip hatalarını gösterecektir ve değişebilir durum yoktur.
Ingo

0

Diğer yanıtların da belirttiği gibi, bir programlama dili uygulanırken yazmanın iki yaklaşımı vardır.

  1. Programcıya tüm değişkenlerin ve fonksiyonların türler için ne kullandığını söylemesini sağlayın. İdeal olarak, tip spesifikasyonlarının doğru olduğunu da doğrulamanız gerekir. Daha sonra, her yerde ne tür bir şey olacağını bildiğiniz için, uygun şeyin orada olacağını varsayan ve bu türü doğrudan uygulamak için kullandığınız veri yapısını kullanan bir kod yazabilirsiniz.
  2. Değişkenlerde saklanacak ve işlevlere aktarılacak ve işlevlerden döndürülecek değerlere bir tür göstergesi ekleyin. Bu, programlayıcının değişkenler veya işlevler için herhangi bir tür belirtmesi gerekmeyeceği anlamına gelir, çünkü türler aslında değişkenlerin ve işlevlerin başvurduğu nesnelere aittir.

Her iki yaklaşım da geçerlidir ve hangisinin kullanılacağı kısmen performans gibi teknik hususlara ve kısmen de dil için hedef pazar gibi politik nedenlere bağlıdır.


0

Her şeyden önce, dinamik diller esas olarak kullanım kolaylığı için yaratılmıştır. Bahsettiğiniz gibi, otomatik olarak tür dönüşümü almak ve bize daha az ek yük sağlamak gerçekten iyidir. Ancak aynı zamanda performans sorunları da yok.

Performans hakkında endişelenmemeniz durumunda dinamik dillere bağlı kalabilirsiniz. Örneğin, JavaScript'in programınızda birçok tür dönüştürme gerçekleştirmesi gerektiğinde daha yavaş çalıştığını, ancak kodunuzdaki satır sayısını azaltmaya yardımcı olduğunu varsayalım.

Ve belirtmek gerekirse, programcının türü belirtmesine izin veren başka dinamik diller de vardır. Örneğin Groovy , JVM üzerinde çalışan ünlü dinamik dillerden biridir. Ve son günlerde bile çok ünlü oldu. Groovy performansının Java ile aynı olduğunu unutmayın.

Umarım size yardımcı olur.


-1

Bunu yapmak hiç mantıklı değil.

Neden?

DTL'lerin tip sistemi tam olarak öyle olduğu için türler derleme zamanında belirlenemez. Bu nedenle, derleyici belirtilen türün anlamlı olup olmadığını kontrol edemedi.


1
Neden? Bir derleyiciye ne tür beklentilerle ilgili ipucu vermek mükemmel bir mantıklı. Herhangi bir tür sistem kısıtlamasıyla çelişmez.
SK-mantığı

1
SK-logic: Dinamik olarak yazılırsa, her işlev / yöntem / işlemin "Dinamik", "Herhangi" veya her türden nesne aldığını ve "Dinamik", "Herhangi" değerini döndürdüğü anlamına gelirse, genel olarak belirli bir değerin örneğin her zaman bir tamsayı olacaktır. Bu nedenle, çalışma zamanı kodu, tıpkı türün ilk etapta "Dinamik" olduğu gibi, tamsayı olmayanları da kontrol etmelidir. Bu sadece statik tip bir sistemin yaptığı şeydir: belirli bir değişken, alan veya yöntem geri dönüşünün her zaman belirli bir tipte olduğunu kanıtlamayı mümkün kılar .
Ingo

@Ingo, hayır, bir yolu var. Örneğin Common Lisp'de nasıl uygulandığını görün. Özellikle yerel değişkenler için kullanışlıdır - tüm bu yazma ipuçlarını tanıtarak performansı önemli ölçüde artırabilirsiniz.
SK-mantığı

@ SK-logic: Bana CL'de tip hatalarının ne zaman ve nasıl tespit edildiğini söyleyebilirsiniz? Her neyse, @MainMa statükoyu sorusunda oldukça güzel bir şekilde özetledi: Sadece "tamamen" dinamik dillerden bekleyebileceğim şey bu.
Ingo

@Ingo, türlerin yalnızca statik olarak doğruluğunu kanıtlamak için yararlı olduğunu düşündüren şey nedir? Denetlenmeyen tipte bir dökümün olduğu C gibi diller için bile geçerli değildir. Dinamik dillerdeki tür ek açıklamaları çoğunlukla performansı artıran veya somut bir sayısal temsili belirten derleyici ipuçları olarak yararlıdır. Çoğu durumda ek açıklamaların kodun anlambilimini değiştirmemesi gerektiğine katılıyorum.
SK-mantığı

-1

Go'ya bir bakın, yüzeyde statik olarak yazılmıştır, ancak bu türler esasen dinamik olan arayüzler olabilir.

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.