Hangi faydalı alternatif kontrol yapılarını biliyorsunuz? [kapalı]


12

Benzer soru SO'da da kapatıldı.

Bazen programlama yaparken, bazı belirli kontrol yapılarının bizim için çok yararlı olacağını, ancak programlama dilimizde doğrudan bulunmadığını görürüz.

Hangi alternatif kontrol yapılarının hesaplamayı organize etmenin yararlı bir yolu olduğunu düşünüyorsunuz?

Buradaki amaç, parçalamayı ve muhakemeyi geliştirmek için kod yapılandırması hakkında yeni düşünme yolları elde etmektir.

Şu anda kullanılamayan arzu edilen bir sözdizimi / semantik oluşturabilir veya mevcut bir programlama dilinde daha az bilinen bir kontrol yapısından bahsedebilirsiniz.

Yanıtlar, yeni bir programlama dili veya gerçek bir dili geliştirme konusunda fikir vermelidir.

Bunu beyin fırtınası olarak düşünün, bu yüzden çılgın bir fikir olduğunu düşündüğünüz bir şey yayınlayın, ancak bazı senaryoda uygulanabilir olabilir.

Bu zorunlu programlama ile ilgilidir.


1
Bu sorunun neden "zorunlu programlama" ile ilgili olması gerekiyor?
missingfaktor

@missingfaktor: Çünkü kontrol yapıları zorunlu programlama ile ilgilidir. Elbette, bazı problemler fonksiyonel yaklaşımla veya başka bir yolla çözülebilir, ancak diğer paradigmalar kontrol yapılarını gelişim merkezine koymaz. Ama yine de yaratıcı olabilirsiniz.
Maniero

3
Desen Eşleştirme'yi Muhafızlarla paylaşacağım, çünkü bunlar Case ifadeleri ve If-Thens'den daha genel, ama bu bir FP bölgesi değilse, sanırım geri kalanımız için daha fazla Desen Eşleme!
CodexArcanum

@CodexArcanum: Örüntü Eşleştirme, zorunlu yapılara çok benzeyen bir yapıdır. Gerçekten de, Desen Eşleştirme kendisi zorunlu kontrol yapılarına bir alternatiftir. Utangaç olmayın ;-)
Maniero

Tüm cevaplara bakmak, tekliflerin hiçbirinin gerçek hayatta bulunmadığı (ve umarım asla olmayacağı) beni mutlu ediyor. Üzgünüm :)
serg

Yanıtlar:


14

Tamam, bu eğlenceli bir soru.

Ayrıca else, ilk testte durum doğru olmadığında, süre ve döngüler için bir genel olmak istiyorum :

while (condition) {
    // process
}
else {
    // condition was never true
}

Bu durumun garip bir şekilde yeniden hesaplanmasını veya bir değişkende saklanmasını önler.


Python'da bu var.
Barry Brown

Hey! Sonunda kabul ettiğim ilginç bir Python seçimi! ;-)
Macneil

5
Hayır. Döngü normal sona erdiğinde Python'daki / while döngülerindeki else deyimi, döngü bir break veya return deyimi veya bir istisna ile sonlandırılmaz demektir. Döngülerde, diğer clasuse, ilmekli elemanların sırası tükendikten sonra yürütülür ve döngüler sırasında, döngü koşulu ilk kez False olarak değerlendirildikten sonra yürütülür.
pillmuncher

4
Macneil'in PHP'ye açıkladığı şekilde yapıyı eklemek için bir istek var while ... else. Bence bu harika bir fikir, çünkü "sonuçlar burada / sonuç yoktu" web uygulamalarında oldukça yaygın bir deyim.
Dean Harding

1
@SnOrfus: YALNIZCA while koşulu karşılanmazsa çalışan bir kod bloğu (loop bloğundan ayrı) ister. Do-While, while koşuluna bakılmaksızın, döngünün kod bloğunu (bazı ayrı bloklar değil) yürütür.
Lejyon

10

Neden birkaç cevabı bir araya getirmiyorsunuz?

while (expr) {

    // Executed every iteration, unless first{} is present.
    // May be explicitly called rest{} if you like first{} to come first.

    // Blocks may return results, and consequently be used in expressions.
    return expr;

} first {

    // Executed only on the first iteration.

} pre {

    // Executed before every iteration.

} post {

    // Executed after every iteration.

} catch (oops) {

    // All blocks are implicitly try{}ed if followed by a catch{}.

} finally {

    // Executes after the block completes, regardless of exceptions.

} else {

    // Executed if the loop body or rest{} never executes.

} never {

    // Executes only when a client is present.

} drop (bad, worse), // Explicitly ignore certain exceptions.
  until (expr);      // Here, have a post-body condition, too.

Zorunlu bir dilde genişletilebilir, genelleştirilmiş bir akış kontrol yapısı sözdizimi oldukça yararlı ve eğlenceli olacaktır. Bu görününceye kadar, sanırım sadece Lisp falan kullanacağım.


5
Yararlı değil, kafa karıştırıcı. Eğlenceli değil, yavaş.
Josh K

2
@Josh K: Evet, haklısın. Ne, katılmıyorum diye düşündün mü? Bu cevap gülmekten kaçınmak için dilini ısırıyor.
Jon Purdy

İronik olması gerekiyorsa kesinlikle başarılı oldu!
Josh K

11
+1 Beni güldürdü. Kodun yinelemeler arasında yürütülmesi için bir "arasında" yan tümcesi gerekir.
Barry Brown

1
+1, ama bir de ihtiyacı var seventh { ... }.
j_random_hacker

7

Fonksiyonlar olarak kontrol yapıları.

İstediğim for, if, else, while, vb fonksiyonlar, değil özel yapılar olmak.

İstediğim return, try/exceptve gotodevamlılık gösteren türevleri olmak.

Bunun elbette belirli bir kontrol yapısı ile ilgisi yoktur ve genel olarak kontrol yapılarını, kontrol yapılarının metalarını nasıl gördüğünüzle ilgilidir.


2
Devamlar bir dil için ağır bir kavramdır ve bunları birçok dilden çıkarmak için iyi nedenler vardır.
David Thornley

Ben katılmıyorum; ,,, ve as işlevlerine sahip forolmak if, bu işlevlere ait parametrelerin, orijinal yapılarla aynı şekilde davranabilmesi için tembel bir şekilde yürütülmesi gerektiğini ortaya çıkarıyor. Tembel yürütme becerisine sahip olmak güzel olurdu. elsewhile
Dr.Wily's Apprentice

1
@David: Sadece orada olmaları onları kullanmanız gerektiği anlamına gelmiyor. Düzenli programcılar, alışkın oldukları şeyleri return, istisnaları vb. Kullanabilirler . Ancak şimdi uzman programcı, ihtiyaç duyulduğunda araç kutusunda güçlü bir ek araca sahiptir. Ayrıca, IMHO dilleri “boşuna” olmamalıdır. Diller, artan CS uzmanlığı ve büyüme bilgisini destekleyebilmelidir.
dietbuddha

1
@dietbuddha: (devam) Sürekliliklerin kötü olduğunu söylemiyorum, ağır olduklarını söylüyorum ve bunları kullanılabilir hale getirmenin, istisnalar gibi bir şey için dil üzerinde etkileri var. Ayrıca, süreklilik sahibi olmak, insanların yine C ++ istisnaları gibi, dili kullanma şekillerindeki değişiklikleri zorlar. Sürekliliği destekleyen bir dil, iyi ve kötü yollardan olmayan dilden farklı olacaktır.
David Thornley

1
@ Steve314 - longjmp, benzerlikler olmasına rağmen bir devam değil. Devamlar tüm durumu (tüm yerliler, globaller ve yığın) kaydeder. longjmp bir yığın işaretçisi kaydeder, böylece setjmp'nin kullanıldığı kapsamı aşarsanız çerçeve artık bulunmadığından bir segfault elde edersiniz. Kaydettiği değişkenlerde de bazı sınırlamalar olduğuna inanıyorum.
dietbuddha

6

Bağlantılı makale kesinlikle Donald Knuth'un N + 1/2 Döngüler hakkında doğru anlıyor . C / C ++ / Java ile ifade edilmiştir:

for (;;) {
  get next element;
  if (at the end) break;
  process the element;
}

Bu, bir dosyadan satır veya karakter okumak, EOF'a ulaşıp ulaşmadığınızı test etmek ve daha sonra işlemek için kullanışlıdır. for(;;)..if(..)break;Desenin benim için deyimsel olduğunu görmeye çok alışkınım . ( Okuryazar Programlama kitabında yeniden basılmış olan Knuth makalesini okumadan önce , bu "wtf?" İdi.)

Knuth şu anahtar kelimeleri önerdi loop/while/repeat:

loop:
  S;
while C:
  T;
repeat

Nerede Sve Tsıfır veya daha fazla ifade dizisi için yer tutucular ve Cbir boolean koşuludur. Bir Sifade olmasaydı, bir while döngüsü olurdu ve herhangi bir Tifade yoksa o zaman bir do döngüsü olurdu.

Bu yapının kendisi, sıfır veya daha fazla while Ccümleye izin vererek genelleştirilebilir, böylece sonsuz döngüler ve daha sonra iki kontrole ihtiyaç duyan daha nadir koşullar ifade etmek için mükemmel hale getirilebilir .

Aynı makalede Knuth, istisnaların fırlatılması / yakalanması için yerel bir versiyon olacak bir işaret mekanizması önerdi (goto kullanımına alternatif olarak).

Benim için? Java'nın desteklediği kuyruk çağrısı optimizasyonunu diliyorum, böylece herhangi bir genel kontrol yapısını gerektiği gibi ifade edebilirim .


Güncelleme: Birçok C / C ++ / Java programcısının şu durumlarda gömülü bir atama kullanarak bu sorunu aştığını belirtmeyi unuttum while:

while ((c = getc(f)) != -1) {
   T;
}

Knuth'un yapısından gelen terimler kullanılarak, bu, tek bir ifadede birleştirilebilir Sve Cbirleştirilebilir. Başkalarının görmesini istemem Bazı insanlar, yukarıda gömülü atama görmekten nefret breakiçinde for (;;)yukarıda. Ancak ne zaman Sve Cbirleştirilemedi, örneğin Sbirden fazla ifadeye sahip olduğunda , for (;;)kodu tekrar etmeden tek alternatif budur. Diğer alternatif, Skodu çoğaltmaktır :

S;
while (C) {
  T;
  S;
}

Knuth'un loop/while/repeatalternatifi çok daha iyi görünüyor.


Bu döngü sırasında tekrarlama Pascal repeat-untildöngüsüne çok benziyor .
Mason Wheeler

@Mason: Fark, yalnızca bir değil, ifadelerin yanı sıra durumunuzu ekleyebileceğiniz iki yer olması.
Kasım'da Macneil

Oh, neler olduğunu anlıyorum. Evet, bu ilginç ...
Mason Wheeler

ANSI Basic bir do while ... loop untilön koşul ve son koşul isteğe bağlıdır ve ben (belirsiz) her ikisini de bir döngüde kullanmayı hatırlıyorum. Orta durumunuz için Ada var exit when ...;. En önemli avantajı , birden çok (ancak hepsi değil) iç içe döngülerden bir kerede çıkmak if ... break;için yazabilmenizdir exit loopname when ...;. Muhtemelen bu kopuştan biraz daha görünür.
Steve314

Komik şey. Ada tam da bu özelliğe sahip.
John R. Strohm

6

BCPL dili, bir valueofifade dizisini tek bir ifadeye dönüştürmek için kullanılabilecek bir ifadeye sahipti :

foo(a, b, valueof {some series of statements; resultis v});

Nerede bir some series of statementsşey olabilir ve bütün olarak valueofdeğerlendirir v.

Bu, bir this()veya çağrılması için bir argüman hesaplamanız gerektiğinde Java'da kullanışlı olabilir super()(bu, daha önce hiçbir şey olmamasını gerektirir). Tabii ki, sadece ayrı bir yöntem yazabilirsiniz, ancak bağlam için birçok yerel değerden geçmeniz gerekiyorsa bu bir acı olabilir.

finalGerekli değişkenler için kullanabiliyorsanız , valueofanonim iç sınıfları kullanarak Java'da zaten yapabilirsiniz :

foo(a, b, new Object(){String valueof(){
    String v ...; some series of statements; return v;}}.valueof());

1
GCC bunun için bir uzantıya sahiptir ({ statement1; statement2; ...; result-expr; }). Ben başka yerlerde de benzer gördüm, ama nerede olduğunu hatırlamıyorum. Muhtemelen hepsi BCPL'den kopyalandı.
Steve314

6
unless(condition) {
  // ...
}

ile aynı şeyi yapar:

if(!condition) {
  // ...
}

repeat {
  // ...
} until(condition)

ile aynı şeyi yapar:

do {
  // ...
} while(!condition)

Lisp ...
Duros

1
Veya Ruby, için benzer bir sözdizimine sahiptir unless.
Josh K

2
Oldukça Perlish görünüyor. Bunu yapmanın birden fazla yolu var.

2
@ Steve314 Yanlış destek stili kullanmalısınız . ;-)
Orbling

1
@Orbling - hiç de değil. Herkes başka yanlış ayracı tarzını kullanır.
Steve314

5

Farklı bir notta, programlama dillerinde yineleyiciler için daha iyi destek görmek istiyorum. Özellikle, çift ​​olarak iki koleksiyon aşağı gitmek istediğinizde :

for (String s, Integer i : stringsSet, integersSet) {
    // use the pair (s, i)
}

Bazı dinamik diller zaten buna sahip olabilir veya kütüphaneler ve makrolar aracılığıyla kolayca destekleyebilir, ancak bunun sorunuzun ruhunda olduğunu düşünüyorum.

İki set aynı boyutta değilse, bir istisna atabilir veya elsedöngüden sonra boyutlarda bir fark olduğunu bildirmek için bir döngü olabilir .

Doğal olarak, bunu üç veya daha fazla listeye gitmek için genelleştirebilirsiniz.


Güncelleme: Tekrarlanabilirler arasında Kartezyen ürünü yapmak da yararlı olacaktır:

for (String s, Integer i : stringsSet * integersSet) {
    // use the pair (s, i), each s with each i
}

iç içe döngülerden başka bir şey değildir:

for (String s : stringsSet) {
    for (Integer i : integersSet) {
        // use the pair (s, i), each s with each i
    }
}

Burada sunduğum iki gösterim arasında, çift sayısında bir O (n) ve O (n ^ 2) farkı olduğunu, sadece tek bir karakterin değiştiğinden biraz endişeliyim.


2
Python'da bunu yapan zip ve zip_longest vardır.
pillmuncher

Harika, belki Python'u hafife alıyorum ve yıllar sonra ikinci kez bakmalıyım. Bu bana hatırlatıyor, bazen Kartezyen ürünü de istiyorsun, döngüler için iç içe eşdeğer.
Kasım'da Macneil

1
Her iki Scala durumlar: paste.pocoo.org/show/297429
missingfaktor

1
Kartezyen ürünle ilgili olarak: Yine Python'da. for a, b, c in itertools.product(iter1, iter2, iter3):tembel olarak değerlendirilen Kartezyen ürünü verir. Bu da ne? Belirli bir yineleyicinin permütasyonlarını ve kombinasyonlarını da mı istiyorsunuz? itertools.permutations, itertools.combinations.
aaronasterling

1
Haskell perspektifi: ilk vaka ve liste kavrama için "zipWith" kullanın, ikincisi için liste monad kullanın. Python / Scala örneklerinde olduğu gibi daha zarif. :)
LennyProgrammers

5

"Dijkstra'nın Döngüsü" ("Dijkstra'nın Korumalı Döngüsü" olarak da bilinir) vardır. Bu tanımlandı Güvenlikli Command Language (GCL) . Sözdizimi ve semantik hakkında bazı bilgileri yukarıdaki 6 Tekrarlama bölümündeki Wikipedia makalesinde bulabilirsiniz : do .

Bugünlerde bu kontrol düzeneğini doğrudan destekleyen bir programlama dili biliyorum. Öyle Oberon-07 (PDF, 70 KB). Ve while ifadesi ile "Dijkstra's Loop" u destekler. Bölüm 9.6'ya bakınız. Yukarıdaki PDF'deki ifadeler ise.

WHILE m > n DO m := m – n 
ELSIF n > m DO n := n – m 
END

PS Bu benim SO cevabımın kopyası .


Model denetleyicisi Spin'e de benziyor, aynı semantik ve temel olarak aynı sözdizimi ile bu yapıya sahip.
j_random_hacker

4

Yerleşik geri izlemeli simge stili ifadeler.

Python, Icon jeneratör avantajlarından çok yararlanır ve genel olarak IMO'dan daha iyi bir iş çıkarır. Prensip olarak, geri izleme sadece bir tür istisna atışıydı, ancak ifadelerin basitliği ...

x = (a / b) else c;

sıfıra bölme gibi hata durumlarını ele almak.

Icon çıldırdı - boolean döndüren karşılaştırma işleçleri yok. Karşılaştırmalar her zaman başarılı oldu veya geri izlemeyi tetikledi ve şimdi umutsuzca hatırlamaya çalıştığım başka bir anlamsal sorun vardı ... hadi, muhtemelen unutulduğundan daha fazla bastırıldığını söyleyelim.

Her zaman ifbaşka hiçbir if (condition, success-value)şeyleri olmayan bir ifadeye sahip olmaları gerektiğini düşündüm - durum yanlış döndürürse geri izleme - ve garip karşılaştırmaları bırak.

EDIT hatırlıyorum - gerçekten açık. İki argümanla karşılaştırma başarılı veya başarısız olur - döndürülecek yeni bir değer hesaplamaz. Bu yüzden başarılı olduğunda, ne yok onu dönmek? Cevap - argümanlardan biri. Ama yazarsanız a > b, geri dönmek için mantıklı argüman hangisidir - aveya b? Peki ya b < abunun yerine yazarsanız ? Ben düşünüyorum her zaman bir şey olduğu kadar his gibi yapar sağ argüman, döndü, ama yine de genellikle bana yanlış argüman gibi görünüyordu.


4

Bu sadece genel bir fikir ve sözdizimidir:

if (cond)
   //do something
else (cond)
   //do something
also (cond)
   //do something
else
   //do something
end

AYRICA durum daima değerlendirilir. ELSE her zamanki gibi çalışır.

Dava için de çalışır. Muhtemelen break ifadesini ortadan kaldırmanın iyi bir yoludur:

case (exp)
   also (const)
      //do something
   else (const)
      //do something
   also (const)
      //do something
   else
      //do something
end

şu şekilde okunabilir:

switch (exp)
   case (const)
      //do something
   case (const)
      //do something
      break
   case (const)
      //do something
   default
      //do something
end

Bunun okunması yararlı mı yoksa basit mi bilmiyorum ama bu bir örnek.


3

Devam Geçiş Tarzı akla geliyor. Ardından, elbette, Kuyruk Çağrısı Optimizasyonuna da sahip olmak istersiniz .


1
Bunun büyük bir hayranı değil ve bunun gerçekten bir "kontrol yapısı" olduğuna inanmıyorum, daha ziyade fonksiyonel dillerde ve programlama tarzında bir yapı taşı. Node.js olsa oldukça bağlı görünüyor.
Josh K

1
Tabii ki bu bir kontrol yapısı. 'İf' veya 'for' gibi bir anahtar kelimeyle gelen anahtar kelime değil, kontrol akışını (dolayısıyla kontrol yapısı) yapılandırmak için bir model olarak gelir. Hatta birçok derleyici tarafından perde arkasında bile kullanılıyor. Üstelik FL'lerle de sınırlı değil. Birinci sınıf nesneler gibi fonksiyonlara ihtiyacınız var.
pillmuncher

1
Bu günlerde C ve C ++ 'da kuyruk çağrı optimizasyonu elde edersiniz, ancak IMO bu noktayı kaçırır. Nokta tam o olduğunu bir optimizasyon. Şema'da, gerçek bir kuyruk çağrısı açıktır. Özellikle C ++ 'da pek çok şey kuyruk çağrınızın kuyruk çağrısı olmadığı anlamına gelebilir. Yığın taşması uygulamanızın bozulduğu anlamına gelir. IMO, bir goto return ...;deyim gibi bir şey olmalı , kuyruk çağrısını açık hale getirme niyeti açık olmalı, bu yüzden derleyici yinelemeyi tekrarlayamazsa bu bir hatadır.
Steve314

1
@Macneil - kesin, kuyruk çağrı optimizasyonu için bildiğim GCC, Clang ve Visual C ++ 'da yapılır. GCC, özyinelemeden yinelemeye kadar daha karmaşık dönüşümlere sahiptir, bu da kuyruk özyineleme olmayan bir dizi durumu ele alabilir. Ama bir çok şey ters gidebilir. Bu kuyruk çağrısında yerel bir değişkene bir işaretçi geçirin ve değişkenin canlı tutulması gerektiğinden yığın çerçevesi kaldırılamaz. C ++ 'da, yerel değişken yıkıcılar normalde "kuyruk" çağrısı döndükten sonra gerçekleşir, yani hiç kuyruk çağrısı değildir.
Steve314

1
@Mike - bu benim açımdan. Özyinelemeli bir kodlama stili kullanırsanız, kuyruk çağrısı "optimizasyonu" olmadan, kod taşması bir hata olduğundan kod potansiyel olarak bozulur. C ++ 'da bu bir optimizasyon - derleyicinin optimizasyon yapması, böylece iyi olmanıza gerek yok, ancak onlara güvenemezsiniz. Özyinelemeli bir tarzda yazma özgürlüğü istiyorsanız, ancak yığın derinliği sorunları hakkında endişelenmek istemiyorsanız, kuyruk çağrısı eleme optimizasyon değildir - bu bir doğruluk sorunudur. Özyineleme bir şeyi kodlamanın en iyi yoluysa, bunu yapabilmeniz gerekir - yığın taşması hakkında endişelenmenize gerek yoktur.
Steve314

3

Sorunsuz iş parçacığı dallanma, bir işlev gibi sözdizimi vardır, ancak ayrı bir iş parçacığında yürütür ve başlangıçta kendisine geçirilmemiş verilere erişemez.

branch foo(data, to, be, processed){
    //code
    return [resulting, data]
}

Bir şube çağrıldığında hemen bir tanıtıcı döndürür.

handle=foo(here, is, some, data)

Tanıtıcı, görevin tamamlanıp tamamlanmadığını kontrol etmek için kullanılabilir.

handle.finished() //True if the execution is complete

Sonuç, yürütme tamamlanmadan önce istenirse, ana iş parçacığı yalnızca bekler.

[result, storage]=handle.result()

Bu, daha gelişmiş çok iş parçacıklı senaryoları kapsamaz, aksine birden çok çekirdeği kullanmaya başlamak için kolay erişilebilir bir yol sağlar.


Cilk'e bir göz atın, C: en.wikipedia.org/wiki/Cilk'in çok temiz ve basit bir uzantısı . Bunun bir varsa bilmiyorum handle.finished()testi, ancak spawnve syncparalel programlama görevleri% 90'ı için gereken tüm vardır.
j_random_hacker

3
if (cond)
   //do something
else (cond)
   //do something
else (cond)
   //do something
first
   //do something
then
   //do something
else (cond)
   //do something
else
   //do something
end

3 koşuldan herhangi biri doğru olarak değerlendirilirse FIRST ve THEN blokları çalışır. İLK blok koşullu bloktan önce çalışır ve THEN koşullu blok çalıştıktan sonra çalışır.

FIRST ve THEN ifadelerini izleyen ELSE koşullu veya son yazma işlemleri bu bloklardan bağımsızdır.

Şu şekilde okuyabilir:

if (cond)
   first()
   //do something
   then()
else (cond)
   first()
   //do something
   then()
else (cond)
   first()
   //do something
   then()
else (cond)
   //do something
else
   //do something
end


function first()
   //do something
return
function then()
   //do something
return

Bu işlevler sadece okunacak bir formdur. Kapsam oluşturmazlardı. Daha çok Basic'ten bir gosub / dönüş gibi.

Tartışma konusu olarak kullanışlılık ve okunabilirlik.


2

Bazen kendimi ilk yineleme sırasında farklı bir şey yapması gereken bir döngü yazarken buluyorum. Örneğin, <td> etiketleri yerine <th> etiketlerini görüntüleme.

Bu durumu boole bayrağıyla ele alıyorum. Bunun gibi bir şey:

first = true

while (some_condition)
    if (first)
        do_something
        first = false
    else
        do_something_else

Çoğu firstzaman yanlış olacağı zaman her yinelemenin değerini kontrol etmek aptalca görünür .

İlk yinelemede farklı bir döngü gövdesi belirtmek için bir döngü seçeneğine sahip olmak istiyorum. Ayrı bir değişkene gerek yoktur. Derlenen kod da bir taneye ihtiyaç duymaz, çünkü üretilen kodun biri ilk yineleme ve diğeri geri kalanı için olmak üzere iki gövdesi olacaktır.


SO sorusu benzer bir fikre sahiptir, ancak değerlerde "o zaman" operatörü kullanılır. Bu şekilde, muhtemelen çoğaltılmış kodunuz yoktur. Örn.print(out, first "<th>" then "<td>")
Macneil

1
Daha iyi bir yol, yineleme +1'yi başlatmaktır.
Josh K

1
Yaygın durum, örneğin virgül ayırıcılı öğeleri listelemek için işleme ile döngü oluşturuyor. Kesinlikle, bu if (!first) gimme-a-comma ();, ama aynı şey. Yine de sahip olduğum bir itiraz - eğer uygun şekilde sarırsanız, Python string join yöntemi gibi şeylerle sonuçlanırsınız - ancak genellikle temel desene ihtiyacınız vardır, altta yatan döngü sıklıkla tekrar yazılmaya gerek duymaz.
Steve314

Josh'un dediği gibi, elbette, ilk öğeyi döngüden çıkarmak geçerlidir. Virgül ayırıcı durumunda, yinelenen kod anlamına gelir, ancak bu yinelenen bir işlev çağrısı olabilir. Şahsen, verimsizliğini tercih ediyorum if (!first), ancak mikro-optimize ediciler dal tahmin itirazlarını artırabilir.
Steve314

1
@Barry Brown: Döngünün 1. yinelemesinin açılması, bir boole bayrağını kontrol etmekten daha hızlı olabilir veya olmayabilir. Terbiyeli bir dal tahmincisi en kötü ihtimalle ilk 2 iterasyonunu yanlış tahmin edeceğim, tahmin ediyorum :) if (!first)Bir optimizasyon derleyicisinin döngü gövdesinin açılmasının ve kurtulmanın firstnet bir kazanç olacağı kadar küçük olup olmadığına karar vermesini tercih ederim .
j_random_hacker

1

[stackoverflow ile ilgili kendi cevabımdan kopyalandı]


ignoring - Belirli bir kod bloğunda meydana gelen istisnaları yok saymak.

try {
  foo()
} catch {
  case ex: SomeException => /* ignore */
  case ex: SomeOtherException => /* ignore */
}

Göz ardı edilen bir kontrol yapısı ile, daha kısaca ve daha okunaklı olarak şöyle yazabilirsiniz:

ignoring(classOf[SomeException], classOf[SomeOtherException]) {
  foo()
}

[Scala bunu (ve diğer birçok İstisna işleme kontrol yapısını) standart kütüphanesinde util.control paketinde sunar. ]


4
İstisnalar göz ardı edilmemelidir.
Josh K

1
Bunun dışında, bağlamda bir istisna hata olmayabilir.
Steve314

1
@Josh, @Steve: İstisnaları görmezden gelmek isteyebileceğiniz durumlar var. Bu gibi durumlar için bu konuya bakın .
missingfaktor

İstisna, bir şeyin yanlış olabileceğine dair bir uyarıdır. Boş bir try..catchblok bir şeydir; sizi hatayı fark etmeye ve kasten görmezden gelmeye zorlar; kod parçalarını küresel bir yoksaymaya atmak, bu istisnalar atıldığında sorunlara ve zayıf programlama alışkanlıklarına yol açabilir.
Josh K

@Josh - Düz düşünmediğim için sadece iki yorumu sildim - ama bunun için umutlar yüksek. Bu ifade küreselse, muhtemelen katılıyorum - ama bana göre bir blok yapı gibi görünüyor. IOW bir tryblok gibidir, ancak daha sonra değil, yakaladığı ve yoksaydığı istisnaları listeler. Bu, okunabilirlik avantajı bile olabilir - örneğin, eksik bir dosyanın açık çağrıyı okumadan önce bile hata olmadığını okuyucuya bildirmek.
Steve314

1

Onun yerine:

switch(myEnum) {
  case MyEnum.Val1: do1(); ...
  case MyEnum.Val2: do2(); ...
....

Python veya şimdi C # yolunu yapın:

action = val2func[myEnum]
action()

Scala'nın birçok yeni özelliği var.

Son olarak, ekstra işlevsellik sağlamak için Clojure gibi diller genişletilebilir.


1
C bunu da yapabilir. Ve Pascal. Muhtemelen tüm bu eski 70'ler / 80'ler / 90'lar dilleri. Bir işlevler dizisi, işlev işaretçileri dizisi haline gelir, ancak bu önemli değildir. Daha kolay olduğu yerde anonim işlevleriniz olduğunda - bilirsiniz, Lisp,
ML'de olduğu

Steve314 - düzeltme - bu, herhangi bir değeri bir işleve eşleyen bir sözlük örneğidir. Burası, 70'lerin / 80'lerin / 90'ların yapabileceği çoğu şeyden biraz daha temiz hale geliyor.
Job

1

İki fikrim var.

Genellikle ben olduğumu bulmak kendimi tekrar içinde catchbloklar. Bu, yöntemlerin çıkarılmasıyla biraz yardımcı olabilir, ancak yöntemler çok kısasa veya başka bir yönteme layık değilse, gereksiz dağınıklığa neden olabilir. Yani, catchblokları yerleştirmek güzel olurdu :

try {
    // Save something
} catch (Exception e) {
    // Something we do for all Exceptions
    catch (ProcessingException e) {
        // Something we do for all Processing exceptions
        catch (DBExcpetion e) {
            // DBExceptions are a subclass of ProcessingException
        }
        catch (BusinessRuleException e) {
            // BusinessRuleExceptions are also a subclass of ProcessingException
        }
    }
    // Something we do after specific sub class Exceptions
 }

Web programlamada sık sık kendimi sık sık böyle bir şey yapıyorum (bu gerçek bir örnek değil, bu yüzden kurgusal vakaları analiz etmeyin):

Account a = getSavedAccount();
if (a == null) {
    a = getAccountFromSessionId();
}
if (a == null) {
    a = getAccountFromCookieId();
}
if (a == null) {
    a = createNewAccount();
}

Javascript'te (iyi, ECMAScript ve belki de bilmediğim diğerleri), çünkü herhangi bir değer bir koşul olarak değerlendirilebilir ||, yardımcı olabilir.

var a = getAFromLocation1() || getAFromLocation2() || default;

Bunun nasıl göründüğünü gerçekten çok seviyorum ve daha fazla dil, özellikle de sunucu tarafında bazılarının destek vermesini diliyorum. (PHP her şeyi koşul olarak değerlendirebilir, ancak değeri korumak yerine tüm koşullu ifadeyi bir boole'ye dönüştürür. Python veya Ruby hakkında bilmiyorum.) Üç durumdan sonra uygunsuz olabilir, ancak daha fazlasına sahipseniz üç durumdan daha kötü bir yazılım tasarımına sahip olabilirsiniz.


Python sizin || ancak koşullu ifade x if c else ysözdizimini elde ettiğinde , bunun en büyük nedeni, bu anlambilimi kullanan ||ve &&kurnazca buggy olan birçok ifadenin olmasıydı . IIRC yaygın bir durum, tedavi edilen uygulama için geçerli olan bir değerdir (sıfır gibi) false, böylece geçersiz bir geri dönüşün kullanılması için atılır. Ancak - benim cevap WRT Simge programlama dili, hangi gibi ifadeler olabilir bakın get1() else get2() else default.
Steve314

1

Genel anahtar yukarıda söyledi:

 switch(x){
  predicate1:
     dosomething();
  predicate2:
     dosomethingelse();
 }

Haskell'de:

  switch' :: a -> [(a -> Bool, b)] -> b
  switch' a [] = undefined
  switch' a (f,b):xs = if f a
                     then b
                      else switch' a xs

0

C # ben basit switch () { ... }, ama bu tür ifadelerle genişletilebilir kullanmak istiyorum :

switch (value)
{
  // string-based operators:
  case begins "Maria": // to catch Maria Carey
    break;
  case ends "Washington": // to catch George Washington
    break;
  case like "ph": // to catch Phil, Phillip, Sophie
    break;
  case between "Aaron" and "April": // to catch all names between
    break;

  // use non-static variables in case expression:
  case Dao.GetDefaultBabyName():
    break;

  // continuable cases without breaking
  case "John":
    bonus = 25;
  case "Peter":
    salary = 500;
    break;

  // jumps between cases
  case "Aleron":
    // do something
    break;
  case "Bella":
    // do something
    jump "Aleron";
    break;

}

Ve bunun gibi. Numaraları veya diğer türdeki (yani destekler IComparable, IConvertible, ...)

Bu, kodumu daha özlü ve okunabilir hale getirebilir.


Vakalara düşme bilinen bir kötülüktür ve genellikle onsuz iyiyim. Ve atlamalar herhangi bir aklı başında programlama için çok GOTOish. Ancak davada ifadeler ve statik olmayanlar olması hoş bir ek olacaktır.
CodexArcanum

0

@Macneil'in dediği gibi eğlenceli bir soru.

Benim (mütevazı öksürük) keşfettiğim en sevdiğim olağandışı kontrol yapısı, diferansiyel uygulama .

Bazı kullanımları vardır. Benim için ezici kullanım, gereksiz verileri yazışmada tutmanın daha genel probleminin bir örneği olan kullanıcı arayüzlerini programlamaktır. Bir yandan uygulama verileri var, diğer yandan da anlaşmaya varılması gereken UI kontrolleri var. Bu "bağlayıcı" gibi geliyor ama aslında çok daha fazlası var.

Genellikle C veya C ++ 'da makrolarla uygularım. C # bunu el genişleyen ifadeler ile yapmak zorunda. Bu bir acı, ama işe yarıyor.

Bir keresinde Lisp makroları açısından uyguladım ve sonra çok temizdi. Programcının dikkatine ihtiyaç duymadı. Tam bir ayrıştırıcı yazmak ve daha sonra tüm doğru şeyleri üretmek için sorun çıkarırsam, başka bir yapısal dilde de aynı şeyi yapabilirdim. Bu büyük bir proje ve ben yapmadım.


0

"Geleneksel" kontrol yapıları for, çalışan adamı kontrol etmek ve onu iktidardaki kapitalist seçkinlerin yozlaşmış ideolojilerine bağlı tutmakla ilgilidir. Bu yüzden ph0rbunun yerine alternatif kontrol yapıları kullanıyorum. Bu for, ama daha radikal: ph0rBir takım kurumsal BS'i tükürerek bir takım elbise ve kravat takmayacaksınız. ph0rgerçek tutar dostum.

Güçle savaş!


0

En basit fordöngü

for(100)
{
    //Will run for 100 times
}


for(i)
{
    //Will run for i times while i must be a positive integer
}


for(i as a)
{
    //Will run for i times while i must be a positive integer
    //and a is the incremental loop variable starting from 0 and 
    //scoped within the loop
}


for(i as a=2)
{
    //Will run for i times while i must be a positive integer
    //and a is the incremental loop variable starting from 2 and 
    //scoped within the loop
}
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.