Noktalı virgüller ve virgüller neden döngüler için değiştirilir?


49

Birçok dilde (geniş bir liste, C'den JavaScript'e)

  • virgül ,ayrı argümanlar (örneğin func(a, b, c))
  • noktalı virgüller ;sıralı komutları ayırır (örn. instruction1; instruction2; instruction3).

Peki neden aynı dilde tersine bu haritalama olduğunu döngüler için :

for ( init1, init2; condition; inc1, inc2 )
{
    instruction1;
    instruction2;
}

yerine (bana daha doğal görünen ne)

for ( init1; init2, condition, inc1; inc2 )
{
    instruction1;
    instruction2;
}

?

Tabii, for(genellikle) bir fonksiyonu ancak argümanlar (yani init, condition, increment) daha bir dizi talimat daha fonksiyonun argümanları gibi davranırlar.

Değişimi için iyi bir gerekçe var dolayı tarihsel nedenler / a sözleşmeye mı, yoksa ,ve ;döngüler içinde?


1
(İlk gönderim burada. Bu sorunun Programcılara veya SO'ya daha fazla ait olup olmadığından emin değilim, bu yüzden gerekirse, göç etmekten çekinmeyin.)
Piotr Migdal

8
Bu kesinlikle bir Programcılar yazısıdır. Hoşgeldiniz! :-)
Martijn Pieters

1
"Neden olmasın" cevabını verecek - aynı cevabı vererek - "Çünkü birinin bir seçim yapması gerekiyordu ve" Yaptıkları seçim "ile aynı" Neden "{" ve "} seçtiler? "Çünkü"
dediler

2
( "Kullandığımız Neden soru tutarlılık hakkındadır @mattnz ;değil |?" (veya yapmak Neden 'başka' değil 'aksi'? kullanın )) Bir dil için durum, ancak bunların büyük bir sayı değil hangi. Örneğin, "döngüde kısa bir süre için C ile yapıldı (ve inc için birden fazla ifade düşünülmüştü) ve insanlar programcıların tahrişini önlemek için bunu değiştirmek istemiyorlardı" cevabı mükemmeldi.
Piotr Migdal

Belki K & R içinde - - Ben okuma hatırlıyorum virgül operatörü başlangıçta dile eklendiğini için mümkün ifadesinin init-ifadesinde birden fazla değişkeni başlatmak için yapmak.
zwol

Yanıtlar:


18

Öyleyse aynı dillerde neden bu eşleme döngüler için ters çevrilmiştir.

Teknik olarak, haritalama "tersine çevrilmemiştir".

  • Virgüllerle ayrılanlar parametre değildir. (En azından) C ++ ve Java'da bildirimler olabilir, bu yüzden ifadeler bile değiller.
  • Noktalı virgüllerle ayrılanlar da (tek) ifadeler değildir.

Gerçekte burada sahip olduğumuz şey, aynı sembollerin farklı şekilde kullanıldığı farklı bir sözdizimsel bağlamdır. Benzeriyle benzerleri karşılaştırmıyoruz, bu nedenle semantik tutarlılığa dayanan tutarlı bir haritalama için haritalama ve güçlü bir argüman yok.

Öyleyse neden tersini yapmıyorsun?

Eh nedenleri "doğal" anlamı gelen düşünüyorum ,ve ;. İngilizce yazılı dilde, bir noktalı virgül virgülden "daha güçlü" bir aradır ve noktalı virgül için glif virgülden daha belirgindir. Bu iki şey mevcut düzenlemeyi yapmak için birleşiyor (bana!) Daha doğal görünüyor.

Ancak, sözdizimi seçiminin neden yapıldığını kesin olarak bilmenin tek yolu, C tasarımcılarının bize 1970'lerde ne düşündüklerini söyleyebilmeleriydi. Zamanında çok fazla teknik karar verdiğine dair net bir hatıraları olduğundan şüpheliyim.


Tarihi sebeplerden mi / bir kongre mi

C'den önce "for" döngülerinde C benzeri bir sözdizimi kullanan herhangi bir dilin farkında değilim:

  • Donal Fellows, BCPL ve B'nin buna eşdeğer bir yapıya sahip olmadığını belirtti.

  • FORTRAN, COBOL ve Algol-60 (ve Pascal) eşdeğerleri daha az anlamlıydı ve "sözdizimi için C" 'ye benzemeyen sözdizimlerine sahipti.

Ancak C'den sonra gelen C, C ++ ve Java gibi diller açıkça C'nin "için" sözdizimlerini ödünç alıyor.


Öyleyse, ( ,vs ;) felsefesi (zayıf-sıralı ayırıcı) yerine (zayıf-sıralı ayırıcı) değil mi? Yine de benim için argümanların veya ifadelerin daha güçlü aralara ihtiyaç duyup duymadığı açık değildir (çoğu durumda bir dizi ifadede olduğu gibi, araların kapalı olması (bakınız örneğin JavaScript (örn. i++[line break]j++))); "Açıkçası tersine çevrilmiş" değildir.
Piotr Migdal

@PiotrMigdal, sınırlayıcı olarak virgül, virgül işlecinin kullanımını engeller ve for döngüsünün bileşenleri ifadeler yerine ifadelerdir. Bunun önemli etkileri var.

Son yorum, FOR i = e1 TO e2 BY e3 DO cBCPL'nin ne yaptığını merak etmemi sağladı ama görünüşe göre orada BASIC'in sözdizimine daha çok benzeyen (e1..e3 ifadeleri, c komutu) vardı. Kaynak
CVn

1
@PiotrMigdal - "Felsefe", K & R ve geri kalanının 1970'te ne düşündüğü her neyse. Hayal ettiğiniz düşünce derinliğine gittiğini sanmıyorum. (Bir araya gelerek telefon değiştirme yazılımı yığınlarını bir araya getirmekten kaçınmak için "daha yüksek" bir dil kullanmaya çalışıyorlardı.)
Stephen C

Az önce kontrol ettim; forsözdizimi (o değildi C tanıtılan B veya BCPL).
Donal Fellows,

60

Gibi döngüler yazıyoruz:

 for(x = 0; x < 10; x++)

Dil, döngüler şöyle görünecek şekilde tanımlanmış olabilir:

 for(x = 0, x < 10, x++)

Ancak bir while döngüsü kullanılarak uygulanan aynı döngüyü düşünün:

 x = 0;
 while(x < 10)
 {
     x++;
 }

x=0Ve x++ifadelerinin noktalı virgüllerle bittiğine dikkat edin . İşlev çağrısında yapacağınız gibi ifadeler değildir. Noktalı virgül ifadeleri ayırmak için kullanılır ve bir for döngüsündeki üç öğeden ikisi ifadeler olduğundan, orada kullanılan şey budur. Bir for döngüsü sadece böyle bir süre döngü için bir kısayol.

Ek olarak, argümanlar bir işleve argümanlar gibi davranmaz. İkinci ve üçüncü tekrar tekrar değerlendirilir. Sıra olmadıkları doğrudur, ancak işlev argümanları da değildir.

Ayrıca, for döngüsünde birden fazla ifadeye sahip olmak için virgül kullanabilmeniz, aslında for döngüsünün dışında yapabileceğiniz bir şeydir.

x = 0, y= 3;

bir for döngüsünün dışında bile mükemmel geçerli bir ifadedir. Gerçi for döngüsü dışında pratik bir kullanım bilmiyorum. Fakat mesele şu ki, virgüller daima ifadeleri alt bölümlere ayırır; for döngüsünün özel bir özelliği değil.


Elbette, "döngü" "temel" iken, bunu anlıyorum. Ama böyle bir "kısa el yazısı" (en azından benim için), x = 0; y = 0;(kıvrık braketin içinde) ile başlayabileceğinizden pek bir anlam ifade etmiyor x++; y++;...
Piotr Migdal

2
@PiotrMigdal, oh yapabilirsin. Demek istediğim, for döngüsü içindeki parçaların ifadeleri (noktalı virgüllerle ayrılmış) ifadeleri değil (virgülle ayrılmış) ifadeleridir
Winston Ewert

1
Farkı alıyorum, sadece benim ;için bir ifadeler dizisi için doğal , herhangi bir ifadeyi ayırmak zorunda değilsiniz (bu sadece tadı farklı mı?). Ve şimdiki konvansiyonda bir zaman zaman ifadelerin sıralarını virgüllerle ayırmakla sona erer ...
Piotr Migdal

3
@PiotrMigdal, yapıların / sendikaların üyeleri noktalı virgüllerle ayrılır, ancak bunlar gerçekten sıralı değildir. Dolayısıyla kesinlikle kullanımdaki bir ifade dizisi ile sınırlı değildir. Günün sonunda, sözdizimi tatmak yerine aşağı gelir.
Winston Ewert,

Ancak for döngüsü dışında pratik bir kullanım bilmiyorum. --- Nasıl? (foo)?bar++, qux++:bletch--- ?:İfadenin sadece bir tane yerine iki şeyi yapmasını istiyorsunuz . Eğer dönüş değeri foodoğrudur olduğunu qux, ancak her iki barve quxartırılır olsun.

15

C ve C ++ 'da virgül operatörüdür, sadece virgül değildir.

Bir fordöngü için gramer gibi bir şey

for ([pre-expression]; [terminate-condition]; [increment-expression]) body-expression

Sorunuz durumunda:

pre-expression -> init1, init2
terminate-condition -> condition
increment-expression -> inc1, inc2

Virgül operatörünün, bir derlemede birden çok eylem gerçekleştirmenize izin verdiğini unutmayın (derleyici tarafından görüldüğü gibi). Öneriniz yerine getirildiyse, programcının virgül operatörü ifadesi veya ayırıcı yazmayı düşündüğü zaman dilbilgisinde bir belirsizlik olacaktır.

Kısacası, ;bir ifadenin sonunu belirtir. Bir fordöngü ile çevrili isteğe bağlı tabloların listesini ve ardından bir anahtar kelimedir (). Virgül operatörü ifadesi, ,tek bir ifadede kullanımına izin verir .


3
Bir for döngüsü, noktalı virgüllerle ayrılmış bir ifadeler kümesidir. İfadeler ifadelerden çok daha fazlası olabilir - biri bir vaka ifadesini ya da if ifadesini bir for döngüsü parçası içine katamaz. Bir for döngüsünün bnf formuna bakıldığında

@MichaelT: Fakat C ++ 'da bir fordöngünün sözdizimi , ilk bölümü olarak bir ifadeye (bildirime) açıkça izin verir. (C ++, kendinden önceki C89’un aksine, orta işlev ilanlarına izin verdi). Bu tür ifadeleri, C ve C ++ kadar yakın 2 dilde bile diller arasında genelleştiremezsiniz.
MSalters

@MichaelT 'Gibi bir şey' bölümünü özledin mi?
James,

@James Eğer gerçek BNF kullanarak "gibi bir şey" önleyebilirsiniz for ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>için C ve for ( for-init-statement; conditionopt ; expressionopt ) statementiçin C ++ --- ';' sadece bir ifade sonlandırıcısını ifade etmez. Bir for döngüsünü () içindeki ifadeler izlemez.

8

Kavramsal geri dönüş yoktur.

C'deki noktalı virgül, virgüllerden daha büyük bölümleri temsil eder. İfadeleri ve beyanları ayırırlar.

For döngüsünün ana bölümleri, üç ifade (veya bir bildiri ve iki ifade) ve bir cisim olduğudur.

Döngüler için C de gördüğünüz virgüller, özellikle for döngünün sözdiziminin bir parçası değildir. Bunlar sadece virgül operatörünün tezahürleri.

Virgüller, işlev çağrılarındaki argümanlar ile işlev bildirimlerindeki parametreler arasındaki ana ayırıcılardır, ancak noktalı virgüller kullanılmaz. For döngüsü özel bir sözdizimidir; işlevlerle veya işlev çağrılarıyla ilgisi yoktur.


2

Belki bu, C / C ++ için özel bir şeydir, ancak bu cevabı gönderiyorum, çünkü açıkladığınız lagnülasyonların sözdizimi çoğunlukla C-Sözdizimi'nden etkilenir.

Daha önce cevaplanmış soruların yanı sıra, teknik açıdan da doğrudur, çünkü aynı zamanda C (ve C ++) 'da virgül aslında bir operatördür , hatta aşırı yükleyebilirsiniz . Bir noktalı virgül işleç ( operator;()) kullanılması, derleyici yazmayı zorlaştırır, çünkü noktalı virgül aksiyomatik ifade sonlandırıcıdır.

Bu müdahaleyi yapan şey, virgülün tüm dilde ayırıcı olarak yaygın şekilde kullanıldığı gerçeğidir . Virgül operatörü bir istisna gibi gözüküyor, çoğunlukla forbirden fazla koşulun çalışmasına neden olmak için kullanılıyor , peki sorun ne?

Aslında, operator,tanımlarda, argüman listelerinde ve benzerlerinde olduğu gibi aynı şeyi yapmak için inşa edilmiştir: İfadeleri ayırmak için inşa edilmiştir - sözdizimsel yapının ,yapamayacağı bir şey. Sadece standartta tanımlanmış olanları ayırabilir.

Ancak, noktalı virgül ayrı değildir - sona erer . Bu da bizi asıl soruya götüren şeydir:

for (int a = 0, float b = 0.0f; a < 100 && b < 100.0f; a++, b += 1.0f)
    printf("%d: %f", a, b);

Virgül, üç döngü bölümündeki ifadeleri ayırırken, noktalı virgül döngü tanımının bir bölümünü (başlatma, koşul veya sonradan) sonlandırır.

Daha yeni programlama dilleri (C # gibi) virgül operatörünün aşırı yüklenmesine izin vermeyebilir, ancak büyük olasılıkla sözdizimini korudular, çünkü değiştirmek onu bir şekilde doğal hissetmiyor.


Bu argümanla ilgili bir sorun var. Bir forifadede, ;sembol açıkça bir ayırıcı olarak kullanılır. İfadenin sözdizimsel 3 bölümünü ayırır. İlerici ifade listesini "sonlandırmak" için 3. noktalı virgül yoktur. Farklı bir simge ile sonlandırılır - ).
Stephen C

0

Benim için dilsel anlamlarına daha az benzer bir anlam kullanıyorlar. Virgüller, daha ayrı bölümleri olan listelerde ve noktalı virgüllerde kullanılır.

İçinde func(a, b, c)argümanların bir listesi var.

instruction1; instruction2; instruction3 belki bir liste ama ayrı ve bağımsız talimatların bir listesidir.

İçinde for ( init1, init2; condition; inc1, inc2 )üç ayrı bölüm varken , bir başlangıç ​​listesi, bir koşul ve artış ifadelerinin bir listesi vardır.


0

Bunu görmenin en kolay yolu şudur:

for(x = 0; x < 10; x++)

dır-dir:

for(
x = 0;
x < 10;
x++
)

Başka bir deyişle, bu x = 0 olayı aslında bir parametre yerine bir ifade / talimattır. Oraya bir ifade eklediniz. Dolayısıyla, noktalı virgülle ayrılırlar.

Aslında, virgülle ayrılmalarının bir yolu yoktur. En son ne zaman bir parametre olarak x <10 gibi şeyler eklersiniz? Bunu bir kez x <10 bilgisayarı yapmak istiyorsanız ve o işlemin sonucunu parametre olarak ekleyin. Öyleyse virgül dünyasında, x <0 değerini bir işleve aktarmak istiyorsanız, x <10 koyarsınız.

Burada program, döngü her geçtiğinde x <10 kontrol etmelidir. Yani bu bir talimat.

x ++ kesinlikle başka bir talimattır.

Bunların hepsi talimat. Böylece yarı kolonla ayrılırlar.


Bu bir açıklama değil. Noktalı virgülle ayrılmış bir ifadedir. Bir ifade tamamen farklı.

x <10, bir ifade olabilir (bu genellikle noktalı virgülle ayrılır. x = 0 kesinlikle bir ifadedir / yönergelerdir.
user4951, 22.03.04.2005

Bak C BNF - döngü oldu tablolar için, böyle bir diğer ifadeleri kullanmak eğer for switchya return içeride döngü tanımı (yani için for(int i = 0; if(i > 1024) { return; } ; switch (i % 3) { case 0; case 1: i++; case 2: i++; } ) { ... }) --- yapamazsın. Bu bir açıklama değil. Bunun yerinefor ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>

Garip. int i = 0, tamam bir ifadedir, ancak biz esas olarak i'yi int olarak tanımlamak ve ona 0 atamak için yaparız (ayrıca 0 döndürür, ancak yan etki olarak. Yapamazsınız. ({int i = 0; j = i}; j <0; cout << "Merhaba dünya") yapabilirmisiniz? Veya evet sanırım.
user4951 22.03.2013

1
@JimThio: Muhtemelen farkında değilsindir, ama "ifade" ve "ifade" dil standartlarında çok kesin anlamlara sahiptir. int i = 0kesinlikle bir ifade değil. Bir ifadeyi tanımlayan kurallar kümesi, bir ifadeyi neyin teşkil edebileceğini göz önüne alarak oldukça karmaşıktır, ancak yapı TYPE NAME = EXPRESSION, bu kuralların hiçbiriyle eşleşmez.
MSalters
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.