Tip, modern programlama dillerinde değişken isminden sonra neden geçmektedir?


57

Neden hemen hemen tüm modern programlama dillerinde (Go, Rust, Kotlin, Swift, Scala, Nim, hatta Python'un son versiyonları) türler önceden değişken değişken bildiriminde değişken isminden sonra gelir?

Neden x: int = 42ve değil int x = 42?
İkincisi eskisinden daha okunaklı değil mi?
Bu sadece bir trend mi, yoksa bu çözümün arkasında gerçekten anlamlı sebepler var mı?


10
8,

3
Evet, bu tamamen düpedüz. Her ne kadar özellikle Kotlin diline atıfta bulunsa da, soru (ve cevapları) bu uygulamaya sahip tüm diller için geçerlidir.
Robert Harvey


2
Üzgünüm beyler, ne zaman googling yaparken Kotlin hakkındaki soruyu gördüm, ancak "Çünkü Kotlin (Go, Rust, ...) dev ekibi buna karar verdi" gibi cevaplar almamasını rica ettim. Daha yaygın bir cevapla ilgilendim: neden bir tür salgın haline geldi?
Andre Polykanine

2
Hihi, öyleyse, (Nesne) Pascal olan ve başlangıcından bu yana değişken isimlerden sonra türlere sahip olan Delphi, önceki yüzyılın karanlık çağlarında, yeniden moderndi;) Btw, okunabilirlik ne olduğunuzu çok etkiliyor. alışığım. Delphi'den gelince, C # var ismine göre türüyle bir süre kafamı çarptı.
Marjan Venema

Yanıtlar:


64

Bahsettiğiniz dillerin tümü, tür çıkarımını desteklemektedir ; bu , türün, bu dillerdeki bildirimin isteğe bağlı bir parçası olduğu anlamına gelir ; çünkü, kolayca tanımlanabilen bir türden bir başlatma ifadesi sağladığınızda, kendileri dolduracak kadar akıllıdırlar.

Bu önemlidir, çünkü bir ifadenin isteğe bağlı bölümlerini daha sağa koymak, ayrıştırma belirsizliğini azaltır ve bu kısmı kullanan ifadelerle tutarlı olmayan ifadeler arasındaki tutarlılığı artırır. varİsteğe bağlı maddelere girmeden önce anahtar kelimenin ve değişken adının zorunlu olduğunu bildiğinizde bir bildirimi ayrıştırmak daha kolaydır . Teoride, bilgisayarlar daha kolay ayrıştırmak için yapmak tüm bunları gerektiği de insanlar için genel okunabilirliği artırmak, ama bu çok daha tartışılır.

Aşağıdaki gibi C ++ gibi bir "non-modern" dil vardır tüm isteğe bağlı tip düzenleyiciler, düşünün, bu argüman özellikle güçlü olur *göstericiler için, &referanslar için const, volatilevb. Birden beyanlar için virgül atmak sonra, aşağıdaki gibi bazı gerçekten garip belirsizlikler olsun başlamak int* a, b;yapmıyor bbir işaretçi.

C ++ bile şimdi "sağdaki tip" bildirimlerini destekliyor auto x = int{ 4 };ve bazı avantajları var .


2
varAyrıştırma basitleştirmesinin çoğunluğunu sağlayan zorunlu anahtar kelimelerin varlığını kabul etmek için +1 .
8,

2
varAnahtar kelimenin varlığı ilk isim yazımının amacını bozmaz mı? var userInput: String = getUserInput()Üzerine yazmanın avantajını görmüyorum String userInput = getUserInput(). Avantaj userInput = getUserInput(), ancak izin verildiğinde de geçerli olacak, ancak bu benim oldukça çılgınca bulduğum bir kapsamlı değişkenin açıklanma bildirimini ima edecektir.
kdb

2
Kdb, C # ve C ++ gibi dillerde olabilir var userInput = getUserInput()ya auto userInput = getUserInput()da derleyici getUserInput()geri dönüşleri bilir , Stringbu yüzden tür kesinti anahtar sözcüğüyle belirtmek zorunda kalmazsınız. userInput = getUserInput()elbette bildirmeden önce kullanmaktır.
Wes Toleman

32

Neden hemen hemen tüm modern programlama dillerinde (Go, Rust, Kotlin, Swift, Scala, Nim, hatta en son Python) tipleri değişken bildiriminden sonra gelir, önceden değil?

Senin öncül iki cephesinde kusurlu:

  • Tanımlayıcıdan önce türüne sahip yeni-ish programlama dilleri vardır . C♯, D veya Ceylon, örneğin.
  • Tanımlayıcıdan sonra türün olması yeni bir fenomen değildir, en azından Pascal'a (1968–1969'da tasarlandı, 1970'te yayınlandı) geri döndü, ama aslında ~ 1902'yi başlatan matematiksel tip teorisinde kullanıldı. Ayrıca ML (1973), CLU (1974), Hope (1970'ler), Modula-2 (1977–1985), Ada (1980), Miranda (1985), Caml (1985), Eiffel (1985), Oberon'da kullanıldı. (1986), Modula-3 (1986-1988) ve Haskell (1989).

Pascal, ML, CLU, Modula-2 ve Miranda'nın hepsi çok etkili dillerdi, bu yüzden bu tip beyanların stilinin popüler kalması şaşırtıcı değil.

Neden x: int = 42ve değil int x = 42? İkincisi eskisinden daha okunaklı değil mi?

Okunabilirlik bir aşinalık meselesidir. Şahsen, Çince’yi okunamayan buluyorum ama görünüşe göre, Çinliler yok. Pascal’ı okulda öğrenmiş, Eiffel, F♯, Haskell ve Scala’ya bakmış ve TypeScript, Fortress, Go, Rust, Kotlin, İdris, Frege, Agda, ML, Ocaml…… .

Bu sadece bir trend mi yoksa böyle bir çözümün arkasındaki gerçekten anlamlı sebepler var mı?

Eğer bir trendse, oldukça ısrarcıdır: Bahsettiğim gibi, matematikte yüz yıl öncesine dayanır.

Tanımlayıcıdan sonra yazı tipine sahip olmanın en önemli avantajlarından biri, çıkarımın istenmesi durumunda yazıyı bırakmanın kolay olmasıdır. Eğer beyanlarınız şöyle görünüyorsa:

val i: Int = 10

O zaman türünü dışarıda bırakmak ve bunun gibi çıkarımı yapmak çok önemlidir:

val i = 10

Bununla birlikte, tür şöyle tanımlayıcıdan önce gelirse:

Int i = 10

Ardından, çözümleyicinin bir ifadeyi bildirimden ayırması zorlaşmaya başlar:

i = 10

Dil tasarımcılarının genellikle ortaya çıkardığı çözüm, tür yerine yazılması gereken bir "tür yazmak istemiyorum" anahtar sözcüğünü tanıtmaktır:

var  i = 10; // C♯
auto i = 10; // C++

Fakat bu aslında pek bir anlam ifade etmiyor: temel olarak açıkça bir tür yazmadığınızı söyleyen bir tür yazmanız gerekiyor. Ha? Sadece dışarıda bırakmak çok daha kolay ve daha mantıklı olurdu, ama bu gramerin daha karmaşık olmasını sağlıyor.

(Ve C'deki fonksiyon işaretçi tipleri hakkında konuşmayalım .)

Yukarıda belirtilen dillerin birçoğunun tasarımcıları bu konuda tartıştılar:

  • Go FAQ (ayrıca bakınız: Go Beyanı Sözdizimi ):

    Bildirimler neden geriye doğru?

    Yalnızca C'ye alışırsanız geriye doğrular. C de, bir değişkenin türünü belirten bir ifade gibi bildirildiği, bunun iyi bir fikir olduğu ifade edilir, ancak tür ve ifade dilbilgileri çok iyi karışmaz ve sonuçlar kafa karıştırıcı olabilir; fonksiyon göstericileri düşünün. Go, çoğunlukla ifadeyi ve yazım sözdizimini ayırır ve işleri basitleştirir ( *işaretçiler için önek kullanmak , kuralı ispatlayan bir istisnadır). C’de beyan

    int* a, b;
    

    abir işaretçi olduğunu beyan eder b; Go'da

    var a, b *int
    

    ikisinin de işaretçi olduğunu açıklar. Bu daha net ve daha düzenli. Ayrıca, :=kısa bir beyan formu tam değişken bildirimi ile aynı düzeni mevcut gerektiğini savunur :=böylece

    var a uint64 = 1
    

    aynı etkiye sahiptir

    a := uint64(1)
    

    Ayrıştırma, yalnızca ifadede kullanılan dilbilgisi olmayan türler için ayrı bir dilbilgisi olmasıyla da kolaylaştırılmıştır; gibi anahtar kelimeler funcve chanişleri açık tutun.

  • Kotlin SSS :

    Neden sağda tip beyanları var?

    Kodu daha okunabilir hale getirdiğine inanıyoruz. Ayrıca, bazı güzel sözdizimsel özellikleri de sağlar. Örneğin, tür ek açıklamalarını dışarıda bırakmak kolaydır. Scala ayrıca oldukça iyi olduğunu kanıtladı, bu bir sorun değil.

  • Scala'da Programlama :

    Java'dan büyük sapma, tür ek açıklamalarının sözdizimi ile ilgilidir - Java'da " variable: Type" yerine " Type variable" dir. Scala'nın postfix tipi sözdizimi Pascal, Modula-2 veya Eiffel'i andırıyor. Bu sapmanın temel nedeni, genellikle bir değişkenin türünü veya bir yöntemin dönüş türünü atlamanıza izin veren tür çıkarımı ile ilgilidir. " variable: Type" Sözdizimini kullanarak bu kolaydır - sadece iki nokta üst üste ve türünü bırakın. Ancak C tarzı " Type variable" sözdiziminde türden basitçe çıkamazsınız; tanımı tanımlamak için artık bir işaretleyici olmaz. Eksik bir tür için yer tutucu olması için alternatif bir anahtar kelimeye ihtiyacınız olacak (bazı tür çıkarımlar yapan C uses 3.0, varbu amaç için kullanır ). Böyle bir alternatif anahtar kelime, Scala'nın yaklaşımından daha geçici ve daha az düzenli hissediyor.

Not: Ceylon tasarımcıları ayrıca neden önek tipi sözdizimi kullandıklarını da belgelemiştir :

Postfix tipi açıklama yerine önek

Niçin C ve Java'yı, önce açıklama adından sonra Pascal ve ML yerine tür ek açıklamalarını koymakta?

Çünkü bunu düşünüyoruz:

shared Float e = ....
shared Float log(Float b, Float x) { ... }

Okumak bundan daha kolay:

shared value e: Float = .... 
shared function log(b: Float, x: Float): Float { ... }

Ve biz sadece bir insanın başka türlü nasıl düşünebileceğini anlamıyoruz!

Şahsen ben onların "argümanını" diğerlerinden daha ikna edici buluyorum.


4
Türünü bırakabilmedir görünüyor ve hala basit ayrıştırma ilavesiyle verilir var var, auto, letdeğil tür bildirimi açık değişkenin hangi yan, ya da benzeri. var Int x = 5veya hatta Int var x = 5her ikisine de kısaltılabilir var x = 5.
8,

5
Alışmaya başladığınızda ve isteğe bağlı tür argümanının güçlü olmasından sonra eşit derecede okunabilir olmasına rağmen, IDE'nin türüne göre değişken isimlerini otomatik olarak öneremediğini belirtmek isterim. TypeScript yazarken bunu özlüyorum.
Pierre Henry

"Your premise is flawed on two fronts" Bunların hepsi C # veya D den daha yeni
Det

3
“Ama bu aslında pek mantıklı gelmiyor: temel olarak açıkça bir tür yazmadığınızı söyleyen bir tür yazmanız gerekiyor.” Tamam, sağdaki tip, örneğinizde tamamen aynı ... Ayrıca anlam ifade etmiyor. Go'daki kadar mantıklı func.
Sopel

4

Pascal bu arada bunu da yapıyor ve yeni bir dil değil. Yine de sıfırdan tasarlanmış bir akademik dildi.

Değişken ismi ile başlamanın anlamsal olarak daha açık olduğunu söyleyebilirim. Tip sadece teknik bir detay. Sınıfınızı olduğu gibi gerçekliğin modeli gibi okumak istiyorsanız, varlıklarınızın adlarını ve teknik uygulamalarını en sonda tutmak mantıklıdır.

C # ve java, C'den kaynaklanır, bu nedenle tecrübeli programcının kafasını karıştırmamak için "önceki tekniğe" saygı duymaları gerekirdi.


3
Ada aynı şekilde yapar, ama Ada kesinlikle "akademik bir dil" değildir.
John R. Strohm

Ada bunu yaptı çünkü Pascal ve Modula 2'den büyük miktarda karıncalandı.
Robot Gort

2
@StevenBurnap, hızlı bir arama Wirth'in Modula-2 hakkındaki ilk kitabının 1982'nin ortalarında ortaya çıktığını ortaya koyuyor. Ada bundan birkaç yıl önce geliştirilme aşamasındaydı (DoD1, 1977'de hatırladığım kadarıyla) ve 1983'te hem ANSI standardı hem de MIL-STD olarak standartlaştı. Ada'ya aday olan ekiplerin dördü PASCAL aldı başlangıç ​​noktaları olarak. (Bell Labs, DoD tarafından C'ye dayanan bir aday dili sunmaya davet edildi. C'nin o zamanlar olmadığını ve
DoD'nin

Yanlış anlıyor olmalıyım. Wirth'in Ada'ya karıştığını sanıyordum.
Robotu

Pascal akademik bir dille başladı, ancak 90'ların sonunda, Delphi aracılığıyla Windows uygulamaları yazmak için dilin dibindeydi, Borland köpekbalıklarını fiyatlandırmayla fırlatıp Java ve C # gel ve ödülü çal. Yine de eski Windows uygulaması dünyasında hala bir ton Delphi göreceksiniz.
Shayne

1

Neden x: int = 42ve değil int x = 42? İkincisi eskisinden daha okunaklı değil mi?

Bu kadar basit bir örnekte, çok fazla fark yok, ancak biraz daha karmaşık hale getirelim: int* a, b;

Bu, C dilinde geçerli ve geçerli bir beyandır, ancak olması gerektiği gibi sezgisel göründüğü gibi yapmaz. Görünüşe göre iki tip değişken ilan ediyoruz int*, fakat aslında bir int*ve bir tane ilan ediyoruz int.

Diliniz yazıyı değişken isimlerinden sonraki açıklamalarına koyarsa , bu problemin üstesinden gelmek imkansızdır.


4
Tür bildirgesini sonradan taşımanın neden bunu etkileyeceğinden emin değilim. Mi x, y *int;iki *intveya tek *intve bir int? İki yerine bir simge yapmak int*ya da *intbir simge çözer :ya da her iki yönde de işe yarayabilecek, benzeri ek sözdizimsel bir eleman kullanır .
8,

@ 8bittree Bildiğim her dilde ad-ilk bildirimlerini kullanan ad ve tür arasında :veya gibi ek bir simge kullanın as.
Mason Wheeler


2
Ve Go'da, x, y *int"x ve y değişkenlerini" pointer-to-int "tipinde belirtmek anlamına gelir.
Vatine,

10
C # önek sözdizimini kullanır, ancak int[] x, yiki dizi gibi davranır . Bu değiştiricileri, değişkene (ve ön ek ve son ekin bir karışımına değil) değişken üzerinde tek bir operatör olarak davranan aptalca C sözdizimidir.
KodlarInChaos
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.