Programlama dillerinde yazma üzerine eğitim programı. Herhangi Bir Dil - Neden Dinamik Yazma? Dinamik yazarak meme

Her şey çok basit. Bir otel ve özel bir daire arasındaki fark gibi.

Dairede sadece orada kayıtlı olanlar yaşıyor. Diyelim ki, Sidorov ailesi içinde yaşıyorsa, o zaman Pupkin ailesi, hayatı boyunca orada yaşayamaz. Aynı zamanda, Petya Sidorov bu dairede yaşayabilir, daha sonra Grisha Sidorov oraya taşınabilir (bazen orada aynı anda yaşayabilirler - bu bir dizidir). Bu statik yazmadır.

Sidorov ailesi otelde bir kez yaşayabilir. Orada bile kayıt olmaları her zaman gerekli değildir. Sonra oradan ayrılacaklar ve Pupkins oraya taşınacak. Ve sonra Kuznetsov'lar. Ve sonra başka biri. Bu dinamik yazmadır.

Programlamaya geri dönersek, ilk durum (statik yazma) örneğin C, C ++, C #, Java ve diğerlerinde gerçekleşir. İlk atamadan önce değişken değer, orada ne depolayacağınızı söylemelisiniz: tamsayılar, kayan noktalı sayılar, dizeler vb. ( Sidorovlar bu dairede yaşayacak). Dinamik yazma ise bunu gerektirmez. Bir değer atarken, aynı anda bir değişkene türünü atamış olursunuz ( Pupkin ailesinden Vasya Pupkin artık bu otel odasında yaşıyor). Bu PHP, Python ve JavaScript gibi dillerde bulunur.

Her iki yaklaşımın da avantajları ve dezavantajları vardır. Hangisinin daha iyi veya daha kötü olduğu, çözülmekte olan görevlere bağlıdır. Daha fazla ayrıntı, örneğin Wikipedia'da bulunabilir.

statik yazma ile değişkenin tipini tam olarak programı yazarken ve algoritmayı geliştirirken bilir ve dikkate alırsınız. onlar. G değişkeninin dört baytlık işaretsiz bir tamsayı olduğunu söylediyseniz, algoritmada her zaman tam olarak dört baytlık işaretsiz bir tamsayı olacaktır (eğer bir şey varsa, o zaman onu açıkça dönüştürmeniz veya çevirmenin onu nasıl dönüştürdüğünü bilmeniz gerekir) belirli durumlar aralığı, ancak temel olarak bir tür uyuşmazlığı varsa, bu bir algoritma hatasıdır ve derleyici en azından sizi uyaracaktır), statik olanla "Aptal Vasya" dizesini sayıya ve eklere koyamazsınız. değişkeni kullanmadan önce "sayı var mı" kontrolleri gerekli değildir, programa girildiği anda veya algoritmanın gerektirdiği şekilde verilerin tüm doğruluğunu gerçekleştirirsiniz.

dinamik yazma ile, genel durumda aynı değişkenin türü sizin tarafınızdan bilinmemektedir ve programın yürütülmesi sırasında zaten değişebilir ve bunu hesaba katarsanız, kimse sizi olası bir algoritma hatası hakkında uyarmaz. tür uyuşmazlığı (bir algoritma geliştirirken, G'nin bir tamsayı olduğunu varsaydınız ve kullanıcı, diyelim ki, bir kayan noktalı sayı veya daha da kötüsü, bir dize girdi veya bir aritmetik işlemden sonra, bir sayı yerine kayan noktalı bir sayı olduğunu söylediniz) integer ve bir sonraki adımda bit işlemlerini kullanmaya çalışacaksınız ...), diğer yandan birçok küçük şeyle uğraşmanıza gerek yok.

Bu makale, dinamik yazmayı kötü, Lisp'i tipsiz bir dil ve C'yi güçlü yazılmış bir dil olarak adlandırmamak için yazma hakkında bilmeniz gereken minimum şeyleri içerir.

V tam versiyon bulunan Detaylı Açıklama her türlü yazım, kod örnekleri, popüler programlama dillerine bağlantılar ve açıklayıcı resimlerle dolu.

Makalenin önce kısa versiyonunu, ardından istenirse tam versiyonunu okumanızı tavsiye ederim.

Kısa versiyon

Yazarak, programlama dilleri genellikle iki büyük kampa ayrılır - yazılan ve yazılmayan (tipsiz). Birincisi, örneğin C, Python, Scala, PHP ve Lua'yı içerirken, ikincisi montaj dili, Forth ve Brainfuck'ı içerir.

"Tipsiz yazma" doğası gereği bir mantar kadar basit olduğundan, ayrıca başka türlere bölünmez. Ancak yazılan diller, birbiriyle örtüşen birkaç kategoriye ayrılır:

  • Statik / dinamik yazma. Statik, değişkenlerin ve işlevlerin son türlerinin derleme zamanında ayarlanmasıyla tanımlanır. Onlar. zaten derleyici hangi türün nerede olduğundan %100 emindir. Dinamik yazımda, tüm türler çalışma zamanında bulunur.

    Örnekler:
    Statik: C, Java, C#;
    Dinamik: Python, JavaScript, Ruby.

  • Güçlü / zayıf yazma (bazen güçlü / zayıf olduğu da söylenir). Güçlü yazım dili, ifadelerde karıştırmaya izin vermediği için öne çıkıyor Çeşitli tipler ve otomatik örtük dönüştürmeler gerçekleştirmez; örneğin, bir diziden bir küme çıkaramazsınız. Zayıf yazılan diller, kesinlik kaybı veya belirsizlik meydana gelse bile, birçok örtük dönüştürmeyi otomatik olarak gerçekleştirir.

    Örnekler:
    Güçlü: Java, Python, Haskell, Lisp;
    Zayıf: C, JavaScript, Visual Basic, PHP.

  • Açık / örtük yazma. Açıkça yazılan diller, yeni değişkenlerin / işlevlerin / bunların argümanlarının açıkça belirtilmesi gerektiğinden farklıdır. Buna göre örtük yazımlı diller bu görevi derleyiciye/yorumlayıcıya kaydırır.

    Örnekler:
    Açık: C ++, D, C #
    Örtük: PHP, Lua, JavaScript

Ayrıca, tüm bu kategorilerin örtüştüğüne dikkat edilmelidir, örneğin, C dilinde statik zayıf açık yazım vardır ve Python dili- dinamik güçlü örtük.

Ancak aynı anda statik ve dinamik yazmanın olduğu diller yoktur. Önden koşmama rağmen, burada yattığımı söyleyeceğim - gerçekten varlar, ama daha sonra bunun hakkında daha fazlası.

Ayrıntılı sürüm

Kısa versiyon sizin için yeterli gelmediyse, iyi. Detaylı yazdığıma şaşmamalı mı? Ana şey, kısa versiyonda tüm yararlı ve ilginç bilgileri sığdırmanın imkansız olması ve ayrıntılı olanın muhtemelen herkesin okuması için çok uzun olmasıydı.

Tipsiz yazma

Tipsiz programlama dillerinde, tüm varlıklar basitçe çeşitli uzunluklardaki bit dizileri olarak kabul edilir.

Tipsiz yazma genellikle düşük seviyeli (birleştirme dili, Forth) ve ezoterik (Brainfuck, HQ9, Piet) dillerde bulunur. Ancak dezavantajlarının yanında bazı avantajları da vardır.

Avantajlar
  • Son derece düşük seviyede yazmaya izin verir ve derleyici/yorumlayıcı herhangi bir tip kontrolüne müdahale etmez. Her türlü veri üzerinde herhangi bir işlem yapmakta özgürsünüz.
  • Ortaya çıkan kod genellikle daha verimlidir.
  • Talimatların şeffaflığı. Dil bilgisi ile, genellikle şu veya bu kodun ne olduğuna dair hiçbir şüphe yoktur.
Dezavantajları
  • Karmaşıklık. Listeler, diziler veya yapılar gibi karmaşık değerleri temsil etmek genellikle gereklidir. Bu uygunsuz olabilir.
  • Kontrol eksikliği. Bir sembolden bir diziye işaretçi çıkarmak gibi anlamsız eylemler, tamamen normal kabul edilecektir ve bu da ince hatalarla doludur.
  • Düşük düzeyde soyutlama. Herhangi bir karmaşık veri türüyle çalışmak, elbette birçok zorluk yaratacak olan sayılarla çalışmaktan farklı değildir.
Güçlü tipsiz yazma?

Evet, bu var. Örneğin, montaj dilinde (x86 / x86-64 mimarisi için, diğerlerini bilmiyorum), rax kaydından (64 bit) cx kaydına (16 bit) veri yüklemeye çalışırsanız programı birleştiremezsiniz. .

mov cx, eax; montaj zamanı hatası

Yani, montajcıda hala yazmanın olduğu ortaya çıktı? Bu kontrollerin yeterli olmadığına inanıyorum. Ve fikriniz, elbette, sadece size bağlı.

Statik ve dinamik yazma

Statik yazmayı dinamik yazmadan ayıran en önemli şey, tüm tür kontrollerinin çalışma zamanında değil derleme zamanında yapılmasıdır.

Bazı insanlar statik yazmanın çok sınırlı olduğunu düşünebilir (aslında öyle, ancak bazı tekniklerin yardımıyla uzun zaman önce ondan kurtuldu). Bazıları için dinamik olarak yazılan diller ateşli bir oyundur, ancak onları öne çıkaran özellikler nelerdir? Her iki türün de var olma şansı var mı? Değilse, neden hem statik hem de dinamik olarak yazılmış birçok dil var?

Anlayalım.

Statik yazmanın faydaları
  • Tür kontrolleri derleme zamanında yalnızca bir kez yapılır. Bu, bir sayıyı bir dizgeye bölmeye çalışıp çalışmadığımızı (ve bir hata mı yoksa bir dönüştürme mi yaptığımız) sürekli olarak bulmamız gerekmeyeceği anlamına gelir.
  • Yürütme hızı. Statik olarak yazılan dillerin neredeyse her zaman dinamik olarak yazılanlardan daha hızlı olduğu önceki noktadan açıktır.
  • Bazı ek koşullar altında, derleme aşamasındaki olası hataları tespit etmenize olanak tanır.
Dinamik yazmanın faydaları
  • Evrensel koleksiyonlar oluşturma kolaylığı - her şeyden ve her şeyden bir sürü (böyle bir ihtiyaç nadiren ortaya çıkar, ancak dinamik yazma ortaya çıktığında yardımcı olacaktır).
  • Genelleştirilmiş algoritmaları tanımlama kolaylığı (örneğin, yalnızca tamsayılar listesinde değil, aynı zamanda gerçek sayılar listesinde ve hatta bir dizi listesinde de çalışacak bir diziyi sıralama).
  • Öğrenmesi kolay - dinamik olarak yazılan diller, programlamaya başlamak için genellikle çok iyidir.

genelleştirilmiş programlama

Tamam, dinamik yazma için en önemli argüman, genel algoritmaları tanımlamanın rahatlığıdır. Bir problem düşünelim - birden fazla dizide (veya listede) arama yapmak için bir fonksiyona ihtiyacımız var - bir tamsayı dizisi, bir gerçek sayı dizisi ve bir dizi karakter.

Nasıl çözeceğiz? 3 tane çözelim farklı diller: bir dinamik olarak yazılmış ve iki statik olarak yazılmış.

Alacağım arama algoritması en basitlerinden biridir - kaba kuvvet. İşlev, gerekli öğeyi, dizinin (veya listenin) kendisini alır ve öğe dizinini veya öğe bulunamazsa (-1) döndürür.

Dinamik çözüm (Python):

Def bul (gerekli_element, liste): numaralandırmadaki (listedeki) (dizin, öğe) için: if element == gerekli_element: dönüş indeks dönüşü (-1)

Gördüğünüz gibi, her şey basit ve başka diziler olmamasına rağmen bir listenin en azından sayıları, hatta listeleri içerebilmesiyle ilgili bir sorun yok. Çok iyi. Devam edelim ve aynı sorunu C'de çözelim!

Statik çözüm (C):

unsigned int find_int (int gerekli_element, int dizisi, unsigned int boyutu) (for (unsigned int i = 0; i)< size; ++i) if (required_element == array[i]) return i; return (-1); } unsigned int find_float(float required_element, float array, unsigned int size) { for (unsigned int i = 0; i < size; ++i) if (required_element == array[i]) return i; return (-1); } unsigned int find_char(char required_element, char array, unsigned int size) { for (unsigned int i = 0; i < size; ++i) if (required_element == array[i]) return i; return (-1); }

Pekala, her işlev ayrı ayrı Python sürümüne benzer, ancak neden üç tane var? Statik programlama gerçekten başarısız oldu mu?

Evet ve hayır. Birini şimdi ele alacağımız birkaç programlama tekniği var. Buna jenerik programlama denir ve C++ dili bunu oldukça iyi destekler. Yeni versiyona bir göz atalım:

Statik çözüm (genel programlama, C ++):

Şablon unsigned int bul (T gerekli_element, std :: vektör dizi) (için (işaretsiz int i = 0; i< array.size(); ++i) if (required_element == array[i]) return i; return (-1); }

TAMAM! Python versiyonundan çok daha karmaşık görünmüyor ve çok fazla yazması gerekmiyor. Ek olarak, sorunu çözmek için sadece 3 tane değil, tüm diziler için bir uygulamamız var!

Bu sürüm tam olarak ihtiyacımız olan şey gibi görünüyor - hem statik yazmanın avantajlarını hem de dinamiğin bazı avantajlarını elde ediyoruz.

Mümkün olması bile harika, ama daha da iyi olabilirdi. İlk olarak, genel programlama daha kullanışlı ve güzel olabilir (örneğin, Haskell dilinde). İkinci olarak, genel programlamaya ek olarak, polimorfizm (sonuç daha kötü olacaktır), fonksiyon aşırı yüklemesi (benzer şekilde) veya makrolar da uygulayabilirsiniz.

statik dinamikler

Birçok statik dilin dinamik yazmaya izin verdiği de belirtilmelidir, örneğin:

  • C #, dinamik sözde türü destekler.
  • F #, dinamik yazmayı simüle etmek için kullanılabilen Operator biçiminde sözdizimsel şekeri destekler.
  • Haskell - dinamik yazma, Data.Dynamic modülü tarafından sağlanır.
  • Delphi - özel tip Variant aracılığıyla.

Ayrıca, dinamik olarak yazılan bazı diller, statik yazımdan yararlanmanıza olanak tanır:

  • Common Lisp - tür bildirimleri.
  • Perl - 5.6 sürümünden beri oldukça sınırlı.

Güçlü ve zayıf yazma

Güçlü yazılan diller, ifadelerde farklı türdeki varlıkların karıştırılmasına izin vermez ve herhangi bir otomatik dönüştürme gerçekleştirmez. Bunlara "güçlü yazılmış diller" de denir. Bunun için İngilizce terim güçlü yazımdır.

Zayıf yazılan diller, aksine, programcının farklı türleri tek bir ifadede karıştırmasını sağlamak için ellerinden geleni yapar ve derleyicinin kendisi her şeyi tek bir türe getirir. Bunlara "gevşek yazılmış diller" de denir. Bunun için İngilizce terim zayıf yazmadır.

Zayıf yazma genellikle tamamen yanlış olan dinamik yazma ile karıştırılır. Dinamik olarak yazılan bir dil hem zayıf hem de güçlü bir şekilde yazılabilir.

Ancak, çok az kişi yazmanın katılığına önem verir. Genellikle, bir dil statik olarak yazılırsa, birçok olası derleme hatası yakalayabileceğiniz iddia edilir. Sana yalan söylüyorlar!

Aynı zamanda, dilin de güçlü bir yazımına sahip olması gerekir. Gerçekten de, derleyici bir hatayı bildirmek yerine, bir sayıya bir dize ekler veya daha da kötüsü, bir diziden bir başkasını çıkarırsa, tüm "tür kontrollerinin" derleme zamanında olması bize ne fayda sağlar? Bu doğru - zayıf statik yazma, güçlü dinamik yazmadan bile daha kötü! (peki bu benim fikrim)

Peki zayıf yazmanın hiçbir avantajı yok mu? Böyle görünebilir, ancak güçlü yazmanın ateşli bir destekçisi olsam da, zayıfın da avantajları olduğunu kabul etmeliyim.

Hangilerini bilmek ister misiniz?

Güçlü yazmanın faydaları
  • Güvenilirlik - Yanlış davranış yerine bir istisna veya derleme hatası alacaksınız.
  • Hız - oldukça pahalı olabilen gizli dönüşümler yerine, güçlü yazma ile bunları açıkça yazmak gerekir, bu da programcının en azından bu kod parçasının yavaş olabileceğini bilmesini sağlar.
  • Programın çalışmasını anlamak - yine, örtük tür dönüştürme yerine, programcı her şeyi kendisi yazar, bu da kabaca bir dize ve sayı karşılaştırmasının sihirle değil kendi başına gerçekleşmediğini anladığı anlamına gelir.
  • Kesinlik - dönüşümleri elle yazdığınızda, tam olarak neye ve neye dönüştüğünüzü bilirsiniz. Ayrıca, bu tür dönüşümlerin doğruluk kaybına ve yanlış sonuçlara yol açabileceğini her zaman anlayacaksınız.
Zayıf yazmanın faydaları
  • Karışık ifadeler kullanma kolaylığı (örneğin, tamsayılardan ve gerçek sayılardan).
  • Yazmadan soyutlama ve göreve odaklanma.
  • Kaydın kısalığı.

Tamam, anladık, zayıf yazmanın da avantajları olduğu ortaya çıktı! Zayıf yazmanın faydalarını güçlü yazmaya aktarmanın yolları var mı?

Hatta iki tane olduğu ortaya çıktı.

Belirsiz durumlarda ve veri kaybı olmadan örtük tip dönüştürme

Uh ... Oldukça uzun bir nokta. "Sınırlı örtük dönüştürme" olarak daha da kısaltayım. Peki, belirsiz durum ve veri kaybı ne anlama geliyor?

Belirsiz bir durum, varlığın hemen anlaşılabilir olduğu bir dönüşüm veya işlemdir. Örneğin, iki sayı eklemek açık bir durumdur. Ve bir sayıyı bir diziye dönüştürmek değildir (belki bir elemandan oluşan bir dizi oluşturulacaktır, belki de böyle bir uzunlukta, varsayılan olarak öğelerle dolu bir dizi veya belki de sayı bir dizeye ve sonra bir diziye dönüştürülecektir. karakter sayısı).

Verileri kaybetmek daha da kolaydır. eğer dönüştürürsek gerçek Numara 3.5'ten bir tamsayıya - bazı verileri kaybedeceğiz (aslında, bu işlem de belirsiz - yuvarlama nasıl yapılacak? Yukarı mı? Aşağı mı? Kesirli kısım atılıyor mu?).

Belirsiz dönüşümler ve kayıplı dönüşümler çok, çok kötü. Programlamada bundan daha kötü bir şey yoktur.

Bana inanmıyorsanız, PL / I dilini öğrenin, hatta sadece özelliklerini araştırın. TÜM veri türleri arasında dönüştürme kuralları vardır! Sadece cehennem!

Tamam, kısıtlı örtük dönüşümü hatırlayalım. Böyle diller var mı? Evet, örneğin Pascal'da bir tamsayıyı gerçek bir sayıya dönüştürebilirsiniz, ancak bunun tersi mümkün değildir. C#, Groovy ve Common Lisp'te de benzer mekanizmalar vardır.

Tamam, güçlü bir dilde zayıf yazmanın birkaç avantajını elde etmenin hala bir yolu olduğunu söyledim. Ve evet, yapıcı polimorfizmi denir ve buna denir.

Örnek olarak harika Haskell dilini kullanarak açıklayacağım.

Polimorfik oluşturucular, sayısal değişmezler kullanılırken en sık güvenli örtük dönüştürmelere ihtiyaç duyulduğu gözleminin bir sonucudur.

Örneğin, pi + 1 ifadesinde pi + 1.0 veya pi + float (1) yazmak istemezsiniz. Sadece pi + 1 yazmak istiyorum!

Ve bu Haskell'de yapılır çünkü değişmez 1'in somut bir türü yoktur. O ne bütün, ne gerçek, ne de karmaşık. Bu sadece bir sayı!

Sonuç olarak, basit bir işlev toplamı xy yazarken, x'ten y'ye tüm sayıları (1'lik bir artışla) çarparak, aynı anda birkaç sürüm elde ederiz - tamsayılar için toplam, gerçek için toplam, rasyonel için toplam, karmaşık sayılar için toplam ve hatta sizin tanımladığınız tüm sayısal türlerin toplamı.

Tabii ki, bu teknik yalnızca sayısal değişmezlerle karışık ifadeler kullanıldığında tasarruf sağlar ve bu, buzdağının sadece görünen kısmıdır.

Bu nedenle, en iyi çözümün, güçlü ve zayıf yazım arasındaki eşiğin üzerinde denge kurmak olduğunu söyleyebiliriz. Ancak şu ana kadar hiçbir dilin mükemmel bir dengesi yok, bu yüzden zayıf yazılmış dillerden (C, JavaScript, Lua, PHP gibi) ziyade güçlü yazılmış dillere (Haskell, Java, C#, Python gibi) daha fazla eğilme eğilimindeyim. .

Açık ve kapalı yazmaya karşı

Açıkça yazılan bir dil, programcının bildirdiği tüm değişkenlerin ve işlevlerin türlerini belirtmesi gerektiğini varsayar. Bunun için İngilizce terim açık yazmadır.

Örtülü olarak yazılan bir dil ise sizi türleri unutmaya ve tür çıkarımı görevini derleyiciye veya yorumlayıcıya bırakmaya davet eder. Bunun için İngilizce terim örtük yazımdır.

İlk başta, örtük yazmanın dinamik yazmaya eşdeğer olduğuna ve açık yazmanın statik yazmaya eşdeğer olduğuna karar verebilirsiniz, ancak daha sonra durumun böyle olmadığını göreceğiz.

Her türün avantajları var mı ve yine bunların kombinasyonları var mı ve her iki yöntemi de destekleyen diller var mı?

Açık Yazmanın Faydaları
  • Her fonksiyon için bir imzanın bulunması (örneğin int add (int, int)) fonksiyonun ne yaptığını kolayca belirlemenizi sağlar.
  • Programcı, belirli bir değişkende ne tür bir değerin saklanabileceğini hemen kaydeder, bu da bunu hatırlama ihtiyacını ortadan kaldırır.
Örtülü Yazmanın Faydaları
  • def add (x, y)'nin kısaltması, int add (int x, int y)'den açıkça daha kısadır.
  • Değişime dayanıklılık. Örneğin, bir işlevdeki geçici değişken, giriş bağımsız değişkeni ile aynı türdeyse, açıkça yazılan bir dilde, giriş bağımsız değişkeninin türü değiştirildiğinde, geçici değişkenin türünün de değiştirilmesi gerekir.

Tamam, her iki yaklaşımın da artıları ve eksileri olduğunu görebilirsiniz (kim başka bir şey bekliyordu?), Öyleyse ikisini birleştirmenin yollarını arayalım!

Seçime göre açık yazma

Varsayılan olarak örtük yazma ve gerekirse değerlerin türünü belirtme yeteneği olan diller vardır. Çevirmen, gerçek ifade türünü otomatik olarak çıkaracaktır. Bu dillerden biri Haskell, netlik için size basit bir örnek vereyim:

Açık tip göstergesi olmadan ekle (x, y) = x + y - Açık tip göstergesi ekle :: (Tamsayı, Tamsayı) -> Tamsayı ekle (x, y) = x + y

Not: Kasıtlı olarak uncurried bir işlev kullandım ve ayrıca daha genel add :: (Num a) -> a -> a -> a yerine kasıtlı olarak özel bir imza yazdım, çünkü Haskell'in sözdizimini açıklamadan fikri göstermek istedim "a.

HM. Gördüğümüz gibi, çok güzel ve kısa. İşlev kaydı, boşluklar dahil bir satırda yalnızca 18 karakter alır!

Ancak, otomatik tür çıkarımı zor bir iştir ve Haskell gibi havalı bir dilde bile bazen başarısız olur. (örnek olarak monomorfizmin kısıtlanması verilebilir)

Varsayılan olarak açıkça yazılan ve zorunlu olarak örtük olarak yazılan diller var mı? Kon
sonsuza kadar.

İsteğe bağlı örtük yazma

C++ 11 (eski adıyla C++ 0x) adlı yeni C++ dil standardı, derleyiciyi bağlama dayalı bir tür çıkarmaya zorlamak için auto anahtar sözcüğünü tanıttı:

Karşılaştırma yapalım: // unsigned type int a = 5'in manuel olarak belirtilmesi; imzasız int b = a + 3; // imzasız türde otomatik kesinti int a = 5; otomatik b = a + 3;

Fena değil. Ancak rekor fazla küçülmedi. Yineleyicilerle bir örnek görelim (anlamadıysanız, korkmayın, ana şey, otomatik çıktı nedeniyle kaydın büyük ölçüde azaldığını belirtmektir):

// std :: vektör tipinin manuel olarak belirtilmesi vec = rastgeleVektör (30); for (std :: vector :: const_iterator it = vec.cbegin (); ...) (...) // Otomatik tür çıkarımı auto vec = randomVector (otuz); for (auto it = vec.cbegin (); ...) (...)

Vay! Bu kısaltmadır. Tamam, ancak geri dönüş türünün argüman türlerine bağlı olacağı Haskell ruhuna uygun bir şeyler yapabilir misiniz?

Ve yine cevap evet, teşekkürler anahtar kelime auto ile birlikte decltype:

// int bölme tipinin manuel olarak belirtilmesi (int x, int y) (...) // Otomatik tip kesinti otomatik bölme (int x, int y) -> decltype (x / y) (...)

Bu gösterim çok iyi gibi görünebilir, ancak genel programlama (şablonlar / jenerikler) ile birleştirildiğinde, örtük yazma veya otomatik tür çıkarımı harikalar yaratır.

Bu sınıflandırmaya göre bazı programlama dilleri

Popüler dillerin kısa bir listesini vereceğim ve her bir "yazma" kategorisi altında nasıl sınıflandırıldıklarını yazacağım.

JavaScript - Dinamik / Zayıf / Kapalı Ruby - Dinamik / Güçlü / Kapalı Python - Dinamik / Güçlü / Kapalı Java - Statik / Güçlü / Açık PHP - Dinamik / Zayıf / Kapalı C - Statik / Zayıf / Açık C ++ - Statik / Yarı- Güçlü / Açık Perl - Dinamik / Zayıf / Kapalı Amaç-C - Statik / Zayıf / Açık C # - Statik / Güçlü / Açık Haskell - Statik / Güçlü / Örtülü Ortak Lisp - Dinamik / Güçlü / Kapalı

Belki bir yerde yanılmışım, özellikle CL, PHP ve Obj-C ile, eğer bir dil hakkında farklı bir fikriniz varsa - yorumları yazın.

  • Dinamik yazma, programlama dillerinde ve belirtim dillerinde yaygın olarak kullanılan bir tekniktir; burada bir değişken, bir değişken bildirildiği anda değil, bir değer atama anında bir türle ilişkilendirilir. Böylece programın farklı bölümlerinde aynı değişken farklı türde değerler alabilir. Dinamik olarak yazılan dillere örnek olarak Smalltalk, Python, Objective-C, Ruby, PHP, Perl, JavaScript, Lisp, xBase, Erlang, Visual Basic verilebilir.

    Zıt teknik, statik yazmadır.

    Dinamik olarak yazmanın zayıf olduğu bazı dillerde, değerleri karşılaştırma sorunu vardır, örneğin, PHP'de "==", "! =" ve "===", "! ==" karşılaştırma işlemleri vardır, burada ikinci işlem çifti ayrıca değerleri ve değişken türlerini de karşılaştırır. "===" işlemi, aşağıdaki ifadeyi doğru kabul eden "=="'den farklı olarak, yalnızca tam eşleşme durumunda true verir: (1 == "1"). Bunun genel olarak dinamik yazma sorunu değil, belirli programlama dilleri sorunu olduğuna dikkat edilmelidir.

Ilgili kavramlar

Bir programlama dili, yazmak için tasarlanmış resmi bir dildir. bilgisayar programları... Bir programlama dili, tanımlayan bir dizi sözcüksel, sözdizimsel ve anlamsal kural tanımlar. dış görünüş yürütücünün (genellikle bir bilgisayar) kontrolü altında gerçekleştireceği programlar ve eylemler.

Bir programlama dilinde sözdizimsel şeker, kullanımı programın davranışını etkilemeyen, ancak dilin kullanımını insanlar için daha uygun hale getiren sözdizimsel özelliklerdir.

Bir özellik, bir tür değişkeni taklit ederek bir nesnenin iç durumuna erişmenin bir yoludur. Bir nesnenin özelliğine erişmek, yapılandırılmış bir alana erişmekle aynı görünür (yapılandırılmış programlamada), ancak gerçekte bir işlev çağrısı yoluyla uygulanır. Bu özelliğin değerini ayarlamaya çalıştığınızda bir metot çağrılır ve bu özelliğin değerini almaya çalıştığınızda başka bir metot çağrılır.

Genişletilmiş Backus – Naur Formu (EBNF), bazı sözdizimsel kategorilerin diğerleri aracılığıyla sırayla tanımlandığı resmi bir sözdizimi tanımlama sistemidir. Bağlamdan bağımsız biçimsel gramerleri tanımlamak için kullanılır. Niklaus Wirth tarafından önerildi. Backus-Naur formlarının genişletilmiş bir işlemidir, daha "kapasiteli" tasarımlarda BNF'den farklıdır ve aynı ifade yeteneği ile basitleştirmeye izin verir ...

Uygulamalı programlama, bir program yazmanın bir nesneyi diğerine sistematik olarak uygulamaktan ibaret olduğu bir bildirimsel programlama türüdür. Böyle bir uygulamanın sonucu yine hem işlev rolünde hem de argüman rolünde uygulamalara katılabilen bir nesnedir, vb. Bu, program kaydını matematiksel olarak netleştirir. Bir fonksiyonun bir ifade ile belirtilmesi, değerler-fonksiyonlar - fonksiyonel ...

Birleştirici programlama dili, iki kod parçasının birleştirilmesinin bunların kompozisyonunu ifade ettiği kavramına dayanan bir programlama dilidir. Böyle bir dilde, işlev argümanlarının örtük gösterimi yaygın olarak kullanılır (bkz. anlamsız programlama), yeni işlevler işlevlerin bir bileşimi olarak tanımlanır ve uygulama yerine birleştirme kullanılır. Bu yaklaşım, uygulamalı programlama ile çelişmektedir.

Değişken, fiziksel veya soyut bir sistemin, genellikle sayısal değerini değiştirebilen bir özelliğidir. Değişken kavramı matematik, fen, mühendislik ve programlama gibi alanlarda yaygın olarak kullanılmaktadır. Değişken örnekleri şunları içerir: hava sıcaklığı, fonksiyon parametresi ve daha fazlası.

Dilbilim ve bilgisayar bilimlerinde sözdizimsel analiz (veya ayrıştırma, jarg. Ayrıştırma ← eng. Ayrıştırma), doğal veya resmi bir dilin doğrusal bir sözlük dizisini (kelimeler, belirteçler) resmi dilbilgisi ile karşılaştırma işlemidir. Sonuç genellikle bir ayrıştırma ağacıdır (sözdizimi ağacı). Genellikle sözcük analizi ile birlikte kullanılır.

Genelleştirilmiş cebirsel veri türü (GADT), yapıcılarının kendisiyle ilişkili kendi türünde olmayan değerleri döndürebilmesi ile karakterize edilen cebirsel veri türü türlerinden biridir. Bağımlı tipteki araştırmacılar arasında endüktif aileler üzerindeki çalışmaların etkisi altında inşa edilmiştir.

Programlamada anlambilim, programlama dillerinin yapılarının anlamlarının biçimsel matematiksel modellerini oluşturarak biçimselleştirilmesini inceleyen bir disiplindir. Bu tür modelleri oluşturmak için araç olarak çeşitli araçlar kullanılabilir, örneğin matematiksel mantık, λ-hesabı, küme teorisi, kategori teorisi, model teorisi, evrensel cebir. Bir programlama dilinin semantiğinin resmileştirilmesi, hem dili tanımlamak hem de dilin özelliklerini tanımlamak için kullanılabilir ...

Nesne yönelimli programlama (OOP), bir programı, her biri belirli bir sınıfın örneği olan nesneler topluluğu olarak temsil etmeye dayanan bir programlama metodolojisidir ve sınıflar bir miras hiyerarşisi oluşturur.

Dinamik değişken - programdaki değişken, içine yerleştirin rasgele erişim belleği altında programın yürütülmesi sırasında tahsis edilir. Aslında, program çalışırken belirli amaçlar için sistem tarafından bir programa tahsis edilen bir bellek parçasıdır. Genel bir statik değişkenden farkı budur - program başlamadan önce sistem tarafından belirli amaçlar için programa tahsis edilen bir bellek parçası. Dinamik bir değişken, değişken bellek sınıflarından biridir.

Bu makale, dinamik yazmayı kötü, Lisp'i tipsiz bir dil ve C'yi güçlü yazılmış bir dil olarak adlandırmamak için yazma hakkında bilmeniz gereken minimum şeyleri içerir.

Tam sürüm, kod örnekleri, popüler programlama dillerine bağlantılar ve açıklayıcı resimlerle dolu her tür yazımın ayrıntılı bir açıklamasını içerir.

Makalenin önce kısa versiyonunu, ardından istenirse tam versiyonunu okumanızı tavsiye ederim.

Kısa versiyon

Yazarak, programlama dilleri genellikle iki büyük kampa ayrılır - yazılan ve yazılmayan (tipsiz). Birincisi, örneğin C, Python, Scala, PHP ve Lua'yı içerirken, ikincisi montaj dili, Forth ve Brainfuck'ı içerir.

"Tipsiz yazma" doğası gereği bir mantar kadar basit olduğundan, ayrıca başka türlere bölünmez. Ancak yazılan diller, birbiriyle örtüşen birkaç kategoriye ayrılır:

  • Statik / dinamik yazma. Statik, değişkenlerin ve işlevlerin son türlerinin derleme zamanında ayarlanmasıyla tanımlanır. Onlar. zaten derleyici hangi türün nerede olduğundan %100 emindir. Dinamik yazımda, tüm türler çalışma zamanında bulunur.

    Örnekler:
    Statik: C, Java, C#;
    Dinamik: Python, JavaScript, Ruby.

  • Güçlü / zayıf yazma (bazen güçlü / zayıf olduğu da söylenir). Güçlü yazım, dilin ifadelerde farklı türlerin karıştırılmasına izin vermemesi ve otomatik örtük dönüştürmeler gerçekleştirmemesi gerçeğiyle ayırt edilir; örneğin, bir dizi bir dizeden çıkarılamaz. Zayıf yazılan diller, kesinlik kaybı veya belirsizlik meydana gelse bile, birçok örtük dönüştürmeyi otomatik olarak gerçekleştirir.

    Örnekler:
    Güçlü: Java, Python, Haskell, Lisp;
    Zayıf: C, JavaScript, Visual Basic, PHP.

  • Açık / örtük yazma. Açıkça yazılan diller, yeni değişkenlerin / işlevlerin / bunların argümanlarının açıkça belirtilmesi gerektiğinden farklıdır. Buna göre örtük yazımlı diller bu görevi derleyiciye/yorumlayıcıya kaydırır.

    Örnekler:
    Açık: C ++, D, C #
    Örtük: PHP, Lua, JavaScript

Ayrıca tüm bu kategorilerin örtüştüğüne dikkat edilmelidir, örneğin C'de statik zayıf açık tipleme vardır ve Python'da dinamik güçlü örtük tipleme vardır.

Ancak aynı anda statik ve dinamik yazmanın olduğu diller yoktur. Önden koşmama rağmen, burada yattığımı söyleyeceğim - gerçekten varlar, ama daha sonra bunun hakkında daha fazlası.

Ayrıntılı sürüm

Kısa versiyon sizin için yeterli gelmediyse, iyi. Detaylı yazdığıma şaşmamalı mı? Ana şey, kısa versiyonda tüm yararlı ve ilginç bilgileri sığdırmanın imkansız olması ve ayrıntılı olanın muhtemelen herkesin okuması için çok uzun olmasıydı.

Tipsiz yazma

Tipsiz programlama dillerinde, tüm varlıklar basitçe çeşitli uzunluklardaki bit dizileri olarak kabul edilir.

Tipsiz yazma genellikle düşük seviyeli (birleştirme dili, Forth) ve ezoterik (Brainfuck, HQ9, Piet) dillerde bulunur. Ancak dezavantajlarının yanında bazı avantajları da vardır.

Avantajlar
  • Son derece düşük seviyede yazmaya izin verir ve derleyici/yorumlayıcı herhangi bir tip kontrolüne müdahale etmez. Her türlü veri üzerinde herhangi bir işlem yapmakta özgürsünüz.
  • Ortaya çıkan kod genellikle daha verimlidir.
  • Talimatların şeffaflığı. Dil bilgisi ile, genellikle şu veya bu kodun ne olduğuna dair hiçbir şüphe yoktur.
Dezavantajları
  • Karmaşıklık. Listeler, diziler veya yapılar gibi karmaşık değerleri temsil etmek genellikle gereklidir. Bu uygunsuz olabilir.
  • Kontrol eksikliği. Bir sembolden bir diziye işaretçi çıkarmak gibi anlamsız eylemler, tamamen normal kabul edilecektir ve bu da ince hatalarla doludur.
  • Düşük düzeyde soyutlama. Herhangi bir karmaşık veri türüyle çalışmak, elbette birçok zorluk yaratacak olan sayılarla çalışmaktan farklı değildir.
Güçlü tipsiz yazma?

Evet, bu var. Örneğin, montaj dilinde (x86 / x86-64 mimarisi için, diğerlerini bilmiyorum), rax kaydından (64 bit) cx kaydına (16 bit) veri yüklemeye çalışırsanız programı birleştiremezsiniz. .

mov cx, eax; montaj zamanı hatası

Yani, montajcıda hala yazmanın olduğu ortaya çıktı? Bu kontrollerin yeterli olmadığına inanıyorum. Ve fikriniz, elbette, sadece size bağlı.

Statik ve dinamik yazma

Statik yazmayı dinamik yazmadan ayıran en önemli şey, tüm tür kontrollerinin çalışma zamanında değil derleme zamanında yapılmasıdır.

Bazı insanlar statik yazmanın çok sınırlı olduğunu düşünebilir (aslında öyle, ancak bazı tekniklerin yardımıyla uzun zaman önce ondan kurtuldu). Bazıları için dinamik olarak yazılan diller ateşli bir oyundur, ancak onları öne çıkaran özellikler nelerdir? Her iki türün de var olma şansı var mı? Değilse, neden hem statik hem de dinamik olarak yazılmış birçok dil var?

Anlayalım.

Statik yazmanın faydaları
  • Tür kontrolleri derleme zamanında yalnızca bir kez yapılır. Bu, bir sayıyı bir dizgeye bölmeye çalışıp çalışmadığımızı (ve bir hata mı yoksa bir dönüştürme mi yaptığımız) sürekli olarak bulmamız gerekmeyeceği anlamına gelir.
  • Yürütme hızı. Statik olarak yazılan dillerin neredeyse her zaman dinamik olarak yazılanlardan daha hızlı olduğu önceki noktadan açıktır.
  • Bazı ek koşullar altında, derleme aşamasındaki olası hataları tespit etmenize olanak tanır.
Dinamik yazmanın faydaları
  • Evrensel koleksiyonlar oluşturma kolaylığı - her şeyden ve her şeyden bir sürü (böyle bir ihtiyaç nadiren ortaya çıkar, ancak dinamik yazma ortaya çıktığında yardımcı olacaktır).
  • Genelleştirilmiş algoritmaları tanımlama kolaylığı (örneğin, yalnızca tamsayılar listesinde değil, aynı zamanda gerçek sayılar listesinde ve hatta bir dizi listesinde de çalışacak bir diziyi sıralama).
  • Öğrenmesi kolay - dinamik olarak yazılan diller, programlamaya başlamak için genellikle çok iyidir.

genelleştirilmiş programlama

Tamam, dinamik yazma için en önemli argüman, genel algoritmaları tanımlamanın rahatlığıdır. Bir problem düşünelim - birden fazla dizide (veya listede) arama yapmak için bir fonksiyona ihtiyacımız var - bir tamsayı dizisi, bir gerçek sayı dizisi ve bir dizi karakter.

Nasıl çözeceğiz? 3 farklı dilde çözelim: biri dinamik yazma ile, ikisi statik yazma ile.

Alacağım arama algoritması en basitlerinden biridir - kaba kuvvet. İşlev, gerekli öğeyi, dizinin (veya listenin) kendisini alır ve öğe dizinini veya öğe bulunamazsa (-1) döndürür.

Dinamik çözüm (Python):

Def bul (gerekli_element, liste): numaralandırmadaki (listedeki) (dizin, öğe) için: if element == gerekli_element: dönüş indeks dönüşü (-1)

Gördüğünüz gibi, her şey basit ve başka diziler olmamasına rağmen bir listenin en azından sayıları, hatta listeleri içerebilmesiyle ilgili bir sorun yok. Çok iyi. Devam edelim ve aynı sorunu C'de çözelim!

Statik çözüm (C):

unsigned int find_int (int gerekli_element, int dizisi, unsigned int boyutu) (for (unsigned int i = 0; i)< size; ++i) if (required_element == array[i]) return i; return (-1); } unsigned int find_float(float required_element, float array, unsigned int size) { for (unsigned int i = 0; i < size; ++i) if (required_element == array[i]) return i; return (-1); } unsigned int find_char(char required_element, char array, unsigned int size) { for (unsigned int i = 0; i < size; ++i) if (required_element == array[i]) return i; return (-1); }

Pekala, her işlev ayrı ayrı Python sürümüne benzer, ancak neden üç tane var? Statik programlama gerçekten başarısız oldu mu?

Evet ve hayır. Birini şimdi ele alacağımız birkaç programlama tekniği var. Buna jenerik programlama denir ve C++ dili bunu oldukça iyi destekler. Yeni versiyona bir göz atalım:

Statik çözüm (genel programlama, C ++):

Şablon unsigned int bul (T gerekli_element, std :: vektör dizi) (için (işaretsiz int i = 0; i< array.size(); ++i) if (required_element == array[i]) return i; return (-1); }

TAMAM! Python versiyonundan çok daha karmaşık görünmüyor ve çok fazla yazması gerekmiyor. Ek olarak, sorunu çözmek için sadece 3 tane değil, tüm diziler için bir uygulamamız var!

Bu sürüm tam olarak ihtiyacımız olan şey gibi görünüyor - hem statik yazmanın avantajlarını hem de dinamiğin bazı avantajlarını elde ediyoruz.

Mümkün olması bile harika, ama daha da iyi olabilirdi. İlk olarak, genel programlama daha kullanışlı ve güzel olabilir (örneğin, Haskell dilinde). İkinci olarak, genel programlamaya ek olarak, polimorfizm (sonuç daha kötü olacaktır), fonksiyon aşırı yüklemesi (benzer şekilde) veya makrolar da uygulayabilirsiniz.

statik dinamikler

Birçok statik dilin dinamik yazmaya izin verdiği de belirtilmelidir, örneğin:

  • C #, dinamik sözde türü destekler.
  • F #, dinamik yazmayı simüle etmek için kullanılabilen Operator biçiminde sözdizimsel şekeri destekler.
  • Haskell - dinamik yazma, Data.Dynamic modülü tarafından sağlanır.
  • Delphi - özel tip Variant aracılığıyla.

Ayrıca, dinamik olarak yazılan bazı diller, statik yazımdan yararlanmanıza olanak tanır:

  • Common Lisp - tür bildirimleri.
  • Perl - 5.6 sürümünden beri oldukça sınırlı.

Güçlü ve zayıf yazma

Güçlü yazılan diller, ifadelerde farklı türdeki varlıkların karıştırılmasına izin vermez ve herhangi bir otomatik dönüştürme gerçekleştirmez. Bunlara "güçlü yazılmış diller" de denir. Bunun için İngilizce terim güçlü yazımdır.

Zayıf yazılan diller, aksine, programcının farklı türleri tek bir ifadede karıştırmasını sağlamak için ellerinden geleni yapar ve derleyicinin kendisi her şeyi tek bir türe getirir. Bunlara "gevşek yazılmış diller" de denir. Bunun için İngilizce terim zayıf yazmadır.

Zayıf yazma genellikle tamamen yanlış olan dinamik yazma ile karıştırılır. Dinamik olarak yazılan bir dil hem zayıf hem de güçlü bir şekilde yazılabilir.

Ancak, çok az kişi yazmanın katılığına önem verir. Genellikle, bir dil statik olarak yazılırsa, birçok olası derleme hatası yakalayabileceğiniz iddia edilir. Sana yalan söylüyorlar!

Aynı zamanda, dilin de güçlü bir yazımına sahip olması gerekir. Gerçekten de, derleyici bir hatayı bildirmek yerine, bir sayıya bir dize ekler veya daha da kötüsü, bir diziden bir başkasını çıkarırsa, tüm "tür kontrollerinin" derleme zamanında olması bize ne fayda sağlar? Bu doğru - zayıf statik yazma, güçlü dinamik yazmadan bile daha kötü! (peki bu benim fikrim)

Peki zayıf yazmanın hiçbir avantajı yok mu? Böyle görünebilir, ancak güçlü yazmanın ateşli bir destekçisi olsam da, zayıfın da avantajları olduğunu kabul etmeliyim.

Hangilerini bilmek ister misiniz?

Güçlü yazmanın faydaları
  • Güvenilirlik - Yanlış davranış yerine bir istisna veya derleme hatası alacaksınız.
  • Hız - oldukça pahalı olabilen gizli dönüşümler yerine, güçlü yazma ile bunları açıkça yazmak gerekir, bu da programcının en azından bu kod parçasının yavaş olabileceğini bilmesini sağlar.
  • Programın çalışmasını anlamak - yine, örtük tür dönüştürme yerine, programcı her şeyi kendisi yazar, bu da kabaca bir dize ve sayı karşılaştırmasının sihirle değil kendi başına gerçekleşmediğini anladığı anlamına gelir.
  • Kesinlik - dönüşümleri elle yazdığınızda, tam olarak neye ve neye dönüştüğünüzü bilirsiniz. Ayrıca, bu tür dönüşümlerin doğruluk kaybına ve yanlış sonuçlara yol açabileceğini her zaman anlayacaksınız.
Zayıf yazmanın faydaları
  • Karışık ifadeler kullanma kolaylığı (örneğin, tamsayılardan ve gerçek sayılardan).
  • Yazmadan soyutlama ve göreve odaklanma.
  • Kaydın kısalığı.

Tamam, anladık, zayıf yazmanın da avantajları olduğu ortaya çıktı! Zayıf yazmanın faydalarını güçlü yazmaya aktarmanın yolları var mı?

Hatta iki tane olduğu ortaya çıktı.

Belirsiz durumlarda ve veri kaybı olmadan örtük tip dönüştürme

Uh ... Oldukça uzun bir nokta. "Sınırlı örtük dönüştürme" olarak daha da kısaltayım. Peki, belirsiz durum ve veri kaybı ne anlama geliyor?

Belirsiz bir durum, varlığın hemen anlaşılabilir olduğu bir dönüşüm veya işlemdir. Örneğin, iki sayı eklemek açık bir durumdur. Ve bir sayıyı bir diziye dönüştürmek değildir (belki bir elemandan oluşan bir dizi oluşturulacaktır, belki de böyle bir uzunlukta, varsayılan olarak öğelerle dolu bir dizi veya belki de sayı bir dizeye ve sonra bir diziye dönüştürülecektir. karakter sayısı).

Verileri kaybetmek daha da kolaydır. 3.5 gerçek sayısını bir tam sayıya çevirirsek, bazı verileri kaybederiz (aslında bu işlem de belirsizdir - yuvarlama nasıl yapılacak? Yukarı mı? Aşağı mı? Kesirli kısım atılıyor mu?).

Belirsiz dönüşümler ve kayıplı dönüşümler çok, çok kötü. Programlamada bundan daha kötü bir şey yoktur.

Bana inanmıyorsanız, PL / I dilini öğrenin, hatta sadece özelliklerini araştırın. TÜM veri türleri arasında dönüştürme kuralları vardır! Sadece cehennem!

Tamam, kısıtlı örtük dönüşümü hatırlayalım. Böyle diller var mı? Evet, örneğin Pascal'da bir tamsayıyı gerçek bir sayıya dönüştürebilirsiniz, ancak bunun tersi mümkün değildir. C#, Groovy ve Common Lisp'te de benzer mekanizmalar vardır.

Tamam, güçlü bir dilde zayıf yazmanın birkaç avantajını elde etmenin hala bir yolu olduğunu söyledim. Ve evet, yapıcı polimorfizmi denir ve buna denir.

Örnek olarak harika Haskell dilini kullanarak açıklayacağım.

Polimorfik oluşturucular, sayısal değişmezler kullanılırken en sık güvenli örtük dönüştürmelere ihtiyaç duyulduğu gözleminin bir sonucudur.

Örneğin, pi + 1 ifadesinde pi + 1.0 veya pi + float (1) yazmak istemezsiniz. Sadece pi + 1 yazmak istiyorum!

Ve bu Haskell'de yapılır çünkü değişmez 1'in somut bir türü yoktur. O ne bütün, ne gerçek, ne de karmaşık. Bu sadece bir sayı!

Sonuç olarak, basit bir işlev toplamı xy yazarken, x'ten y'ye tüm sayıları (1'lik bir artışla) çarparak, aynı anda birkaç sürüm elde ederiz - tamsayılar için toplam, gerçek için toplam, rasyonel için toplam, karmaşık sayılar için toplam ve hatta sizin tanımladığınız tüm sayısal türlerin toplamı.

Tabii ki, bu teknik yalnızca sayısal değişmezlerle karışık ifadeler kullanıldığında tasarruf sağlar ve bu, buzdağının sadece görünen kısmıdır.

Bu nedenle, en iyi çözümün, güçlü ve zayıf yazım arasındaki eşiğin üzerinde denge kurmak olduğunu söyleyebiliriz. Ancak şu ana kadar hiçbir dilin mükemmel bir dengesi yok, bu yüzden zayıf yazılmış dillerden (C, JavaScript, Lua, PHP gibi) ziyade güçlü yazılmış dillere (Haskell, Java, C#, Python gibi) daha fazla eğilme eğilimindeyim. .

Açık ve kapalı yazmaya karşı

Açıkça yazılan bir dil, programcının bildirdiği tüm değişkenlerin ve işlevlerin türlerini belirtmesi gerektiğini varsayar. Bunun için İngilizce terim açık yazmadır.

Örtülü olarak yazılan bir dil ise sizi türleri unutmaya ve tür çıkarımı görevini derleyiciye veya yorumlayıcıya bırakmaya davet eder. Bunun için İngilizce terim örtük yazımdır.

İlk başta, örtük yazmanın dinamik yazmaya eşdeğer olduğuna ve açık yazmanın statik yazmaya eşdeğer olduğuna karar verebilirsiniz, ancak daha sonra durumun böyle olmadığını göreceğiz.

Her türün avantajları var mı ve yine bunların kombinasyonları var mı ve her iki yöntemi de destekleyen diller var mı?

Açık Yazmanın Faydaları
  • Her fonksiyon için bir imzanın bulunması (örneğin int add (int, int)) fonksiyonun ne yaptığını kolayca belirlemenizi sağlar.
  • Programcı, belirli bir değişkende ne tür bir değerin saklanabileceğini hemen kaydeder, bu da bunu hatırlama ihtiyacını ortadan kaldırır.
Örtülü Yazmanın Faydaları
  • def add (x, y)'nin kısaltması, int add (int x, int y)'den açıkça daha kısadır.
  • Değişime dayanıklılık. Örneğin, bir işlevdeki geçici değişken, giriş bağımsız değişkeni ile aynı türdeyse, açıkça yazılan bir dilde, giriş bağımsız değişkeninin türü değiştirildiğinde, geçici değişkenin türünün de değiştirilmesi gerekir.

Tamam, her iki yaklaşımın da artıları ve eksileri olduğunu görebilirsiniz (kim başka bir şey bekliyordu?), Öyleyse ikisini birleştirmenin yollarını arayalım!

Seçime göre açık yazma

Varsayılan olarak örtük yazma ve gerekirse değerlerin türünü belirtme yeteneği olan diller vardır. Çevirmen, gerçek ifade türünü otomatik olarak çıkaracaktır. Bu dillerden biri Haskell, netlik için size basit bir örnek vereyim:

Açık tip göstergesi olmadan ekle (x, y) = x + y - Açık tip göstergesi ekle :: (Tamsayı, Tamsayı) -> Tamsayı ekle (x, y) = x + y

Not: Kasıtlı olarak uncurried bir işlev kullandım ve ayrıca daha genel add :: (Num a) -> a -> a -> a yerine kasıtlı olarak özel bir imza yazdım, çünkü Haskell'in sözdizimini açıklamadan fikri göstermek istedim "a.

HM. Gördüğümüz gibi, çok güzel ve kısa. İşlev kaydı, boşluklar dahil bir satırda yalnızca 18 karakter alır!

Ancak, otomatik tür çıkarımı zor bir iştir ve Haskell gibi havalı bir dilde bile bazen başarısız olur. (örnek olarak monomorfizmin kısıtlanması verilebilir)

Varsayılan olarak açıkça yazılan ve zorunlu olarak örtük olarak yazılan diller var mı? Kon
sonsuza kadar.

İsteğe bağlı örtük yazma

C++ 11 (eski adıyla C++ 0x) adlı yeni C++ dil standardı, derleyiciyi bağlama dayalı bir tür çıkarmaya zorlamak için auto anahtar sözcüğünü tanıttı:

Karşılaştırma yapalım: // unsigned type int a = 5'in manuel olarak belirtilmesi; imzasız int b = a + 3; // imzasız türde otomatik kesinti int a = 5; otomatik b = a + 3;

Fena değil. Ancak rekor fazla küçülmedi. Yineleyicilerle bir örnek görelim (anlamadıysanız, korkmayın, ana şey, otomatik çıktı nedeniyle kaydın büyük ölçüde azaldığını belirtmektir):

// std :: vektör tipinin manuel olarak belirtilmesi vec = rastgeleVektör (30); for (std :: vector :: const_iterator it = vec.cbegin (); ...) (...) // Otomatik tür çıkarımı auto vec = randomVector (otuz); for (auto it = vec.cbegin (); ...) (...)

Vay! Bu kısaltmadır. Tamam, ancak geri dönüş türünün argüman türlerine bağlı olacağı Haskell ruhuna uygun bir şeyler yapabilir misiniz?

Yine, cevap, auto ile birlikte decltype anahtar sözcüğü sayesinde evet:

// int bölme tipinin manuel olarak belirtilmesi (int x, int y) (...) // Otomatik tip kesinti otomatik bölme (int x, int y) -> decltype (x / y) (...)

Bu gösterim çok iyi gibi görünebilir, ancak genel programlama (şablonlar / jenerikler) ile birleştirildiğinde, örtük yazma veya otomatik tür çıkarımı harikalar yaratır.

Bu sınıflandırmaya göre bazı programlama dilleri

Popüler dillerin kısa bir listesini vereceğim ve her bir "yazma" kategorisi altında nasıl sınıflandırıldıklarını yazacağım.

JavaScript - Dinamik / Zayıf / Kapalı Ruby - Dinamik / Güçlü / Kapalı Python - Dinamik / Güçlü / Kapalı Java - Statik / Güçlü / Açık PHP - Dinamik / Zayıf / Kapalı C - Statik / Zayıf / Açık C ++ - Statik / Yarı- Güçlü / Açık Perl - Dinamik / Zayıf / Kapalı Amaç-C - Statik / Zayıf / Açık C # - Statik / Güçlü / Açık Haskell - Statik / Güçlü / Örtülü Ortak Lisp - Dinamik / Güçlü / Kapalı

Belki bir yerde yanılmışım, özellikle CL, PHP ve Obj-C ile, eğer bir dil hakkında farklı bir fikriniz varsa - yorumları yazın.

Çözüm

TAMAM. Yakında hafifleyecek ve yazmakla ilgili söylenecek başka bir şey olmadığını hissediyorum. Oh nasıl? Konu dipsiz mi? Söylenmeyen çok şey var mı? Lütfen faydalı bilgileri yorumlarda paylaşın.