Struktur kontrol alternatif mana yang berguna yang Anda ketahui? [Tutup]

12

Pertanyaan serupa ditutup pada SO.

Terkadang ketika kita sedang pemrograman, kita menemukan bahwa beberapa struktur kontrol tertentu akan sangat berguna bagi kita, tetapi tidak secara langsung tersedia dalam bahasa pemrograman kita.

Struktur kontrol alternatif apa yang menurut Anda merupakan cara yang berguna untuk mengatur komputasi?

Tujuannya di sini adalah untuk mendapatkan cara berpikir baru tentang penataan kode, dalam rangka meningkatkan chunking dan penalaran.

Anda dapat membuat sintaksis semantik / semantik yang tidak tersedia sekarang atau mengutip struktur kontrol yang kurang dikenal pada bahasa pemrograman yang ada.

Jawaban harus memberikan ide untuk bahasa pemrograman baru atau meningkatkan bahasa yang sebenarnya.

Anggap ini sebagai brainstorming, jadi posting sesuatu yang Anda anggap gila, tetapi bisa dilakukan dalam beberapa skenario.

Ini tentang pemrograman imperatif.

Maniero
sumber
1
Mengapa pertanyaan ini harus tentang "pemrograman imperatif"?
missingfaktor
@missingfaktor: Karena struktur kontrol adalah tentang pemrograman imperatif. Tentu, beberapa masalah dapat diselesaikan dengan pendekatan fungsional atau cara lain tetapi paradigma lain tidak menempatkan struktur kontrol sebagai pusat pembangunan. Tapi toh Anda bisa kreatif.
Maniero
3
Yah, saya akan berbagi Pencocokan Pola dengan Pengawal, karena itu lebih umum dari pernyataan Kasus dan Jika-Lalu, tetapi jika ini bukan zona FP, saya kira itu hanya Pencocokan Pola untuk kita semua!
CodexArcanum
@ CodexArcanum: Pola Pencocokan adalah konstruksi yang sangat mirip dengan konstruksi imperatif. Memang, Pencocokan Pola itu sendiri adalah alternatif untuk struktur kontrol imperatif. Jangan malu ;-)
Maniero
Melihat semua jawaban membuat saya senang bahwa tidak ada proposal yang ada di kehidupan nyata (dan mudah-mudahan tidak akan pernah). Maaf :)
serg

Jawaban:

14

Oke, ini pertanyaan yang menyenangkan.

Saya juga ingin memiliki jenderal elseuntuk sementara dan untuk loop, karena ketika kondisi tidak benar pada tes pertama :

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

Ini menghindari komputasi ulang yang canggung dari kondisi atau menyimpannya dalam variabel.

Macneil
sumber
Python memiliki ini.
Barry Brown
Hei! Akhirnya pilihan aneh Python yang saya setujui! ;-)
Macneil
5
Tidak. Klausa lain dalam Python untuk / saat loop dijalankan jika loop berakhir normal, yang berarti, loop tidak diakhiri melalui pernyataan break atau return atau pengecualian. Dalam untuk loop clasuse lain dijalankan setelah urutan elemen yang dilewati habis, dan sementara loop dijalankan setelah kondisi loop mengevaluasi ke False untuk pertama kalinya.
pembuat pil KB
4
Ada permintaan untuk menambahkan while ... elsekonstruk seperti yang dijelaskan Macneil ke PHP. Saya pikir itu ide yang bagus, karena "ini hasilnya / tidak ada hasil" adalah ungkapan yang cukup umum di aplikasi web.
Dean Harding
1
@SnOrfus: Dia menginginkan blok kode (terpisah dari blok loop) yang dijalankan HANYA jika kondisi sementara tidak pernah terpenuhi. Do-While mengeksekusi blok kode loop (bukan blok terpisah) sekali terlepas dari kondisi while.
Legiun
10

Mengapa tidak tumbuk beberapa jawaban menjadi satu?

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.

Sintaksis konstruk kontrol aliran yang dapat diperluas dan disamaratakan dalam bahasa imperatif akan lebih bermanfaat dan menghibur. Sampai itu muncul, kira saya akan menggunakan Lisp atau sesuatu.

Jon Purdy
sumber
5
Tidak berguna, membingungkan. Tidak menghibur, lambat.
Josh K
2
@Josh K: Ya, Anda benar. Apa, kamu pikir aku tidak akan setuju? Jawaban ini menggigit lidahnya agar tidak tertawa.
Jon Purdy
Jika itu dimaksudkan dengan ironis itu pasti berhasil!
Josh K
11
+1 Membuat saya tertawa. Membutuhkan klausa "antara", agar kode dapat dieksekusi di antara iterasi.
Barry Brown
1
+1, tetapi perlu seventh { ... }juga.
j_random_hacker
7

Kontrol struktur sebagai fungsi.

Saya ingin for, if, else, while, dll menjadi fungsi, bukan struktur khusus.

Saya ingin return, try/exceptdan gotomenjadi turunan dari kelanjutan.

Ini tentu saja kurang berkaitan dengan struktur kontrol tertentu dan lebih berkaitan dengan bagaimana Anda melihat struktur kontrol secara umum, meta struktur kontrol.

dietbuddha
sumber
2
Lanjutan adalah konsep kelas berat untuk suatu bahasa, dan ada alasan bagus untuk tidak menggunakan banyak bahasa.
David Thornley
Saya tidak setuju; memiliki for, if, else, dan whilesebagai fungsi membuat saya menyimpulkan bahwa parameter untuk fungsi-fungsi perlu malas dieksekusi untuk berperilaku sama dengan konstruksi aslinya. Memiliki kemampuan untuk melakukan eksekusi malas akan menyenangkan.
Apprentice Dr. Wily
1
@ David: Hanya karena ada di sana, bukan berarti Anda harus menggunakannya. Pemrogram reguler dapat menggunakan apa yang mereka gunakan return, pengecualian, dll. Tapi sekarang programmer ahli memiliki alat tambahan yang kuat di kotak peralatannya jika diperlukan. Selain itu, bahasa IMHO tidak boleh "dibodohi". Bahasa harus memiliki kemampuan untuk mendukung peningkatan keahlian dan pertumbuhan pengetahuan CS.
dietbuddha
1
@dietbuddha: (lanjt) Saya tidak mengatakan kelanjutan buruk, saya katakan mereka kelas berat, dan menjadikannya dapat digunakan memiliki implikasi untuk bahasa, sesuatu seperti pengecualian. Lebih lanjut, memiliki kelanjutan cenderung memaksa perubahan dalam cara orang menggunakan bahasa, sekali lagi seperti pengecualian dalam C ++. Bahasa yang mendukung kelanjutan akan berbeda dari yang tidak, baik dalam cara yang baik maupun buruk.
David Thornley
1
@ Steve314 - longjmp bukan merupakan kelanjutan meskipun ada kesamaan. Kelanjutan menyelamatkan seluruh negara bagian (semua penduduk setempat, global, dan tumpukan). longjmp menyimpan stack pointer jadi jika Anda keluar dari ruang lingkup di mana setjmp digunakan Anda mendapatkan segfault karena frame tidak lagi ada. Saya percaya ada juga beberapa batasan dalam variabel yang disimpannya.
dietbuddha
6

Artikel yang ditautkan pasti benar tentang Loop N + 1/2 Donald Knuth . Dinyatakan dalam C / C ++ / Java:

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

Ini berguna untuk membaca baris atau karakter dari file, menguji apakah Anda telah mencapai EOF, dan kemudian memprosesnya. Saya sudah terbiasa melihat polanya for(;;)..if(..)break;muncul sehingga itu idiomatis bagi saya. (Sebelum saya membaca artikel Knuth, dicetak ulang dalam buku Literate Programming , artikel ini dulunya adalah "wtf?".)

Knuth menyarankan kata kunci loop/while/repeat:

loop:
  S;
while C:
  T;
repeat

Di mana Sdan Tadalah pemegang tempat untuk serangkaian pernyataan nol atau lebih, dan Cmerupakan kondisi boolean. Jika tidak ada Spernyataan maka itu akan menjadi loop sementara, dan jika tidak ada Tpernyataan maka itu akan menjadi loop lakukan.

Konstruk ini sendiri dapat digeneralisasikan dengan mengizinkan nol atau lebih while Cklausa, membuatnya sempurna untuk mengekspresikan loop tak terbatas dan kemudian beberapa kondisi langka yang membutuhkan dua pemeriksaan.

Dalam artikel yang sama, Knuth menyarankan mekanisme pensinyalan yang akan menjadi versi lokal dari pengecualian melempar / menangkap (sebagai alternatif untuk menggunakan goto).

Untuk saya? Saya berharap Java mendukung pengoptimalan tail-call, sehingga saya dapat mengekspresikan struktur kontrol umum apa pun yang diperlukan.


Pembaruan: Saya lupa menyebutkan bahwa banyak programmer C / C ++ / Java menyiasati yang satu ini dengan menggunakan tugas yang disematkan dalam kondisi while:

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

Menggunakan istilah-istilah dari konstruk Knuth, ini diizinkan kapan Sdan Cdapat digabungkan menjadi satu ekspresi. Beberapa orang benci melihat tugas yang disematkan di atas, sementara yang lain benci melihat yang breakdi for (;;)atas. Tetapi ketika Sdan Ctidak dapat digabungkan, seperti ketika Smemiliki beberapa pernyataan, itu for (;;)adalah satu-satunya alternatif tanpa kode berulang. Alternatif lain adalah dengan hanya menggandakan Skode:

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

loop/while/repeatAlternatif Knuth tampaknya jauh lebih baik.

Macneil
sumber
Loop-while-repeat itu terlihat sangat mirip dengan repeat-untilloop Pascal .
Mason Wheeler
@ Alasan: Perbedaannya adalah ada dua tempat Anda dapat memasukkan pernyataan plus kondisi Anda, bukan hanya satu.
Macneil
Oh, aku mengerti apa yang terjadi. Ya, itu menarik ...
Mason Wheeler
ANSI Basic memiliki a do while ... loop until- baik prasyarat dan postkondisi adalah opsional, dan saya (samar-samar) ingat menggunakan keduanya dalam satu loop. Untuk kondisi menengah Anda, ada Ada exit when ...;. Keuntungan utama if ... break;adalah Anda bisa menulis exit loopname when ...;untuk keluar dari banyak (tetapi tidak harus semua) loop bersarang sekaligus. Mungkin sedikit lebih terlihat daripada jeda itu juga.
Steve314
Hal yang lucu. Ada persis fitur itu.
John R. Strohm
6

Bahasa BCPL memiliki valueofekspresi yang dapat digunakan untuk mengubah urutan pernyataan menjadi ekspresi tunggal:

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

Di mana some series of statementsbisa apa saja dan keseluruhannya valueofdievaluasi v.

Ini bisa berguna di Jawa ketika Anda perlu menghitung argumen untuk memanggil this()atau super()(yang mengharuskan tidak ada yang terjadi sebelum itu). Tentu saja, Anda bisa saja menulis metode terpisah, tetapi itu mungkin menyebalkan jika Anda perlu memasukkan banyak nilai lokal untuk konteks.

Jika Anda dapat menggunakan finaluntuk variabel yang diperlukan, Anda sudah bisa melakukan valueofdi Java menggunakan kelas dalam anonim:

foo(a, b, new Object(){String valueof(){
    String v ...; some series of statements; return v;}}.valueof());
Macneil
sumber
1
GCC memiliki ekstensi untuk ini - ({ statement1; statement2; ...; result-expr; }). Saya pernah melihat yang serupa di tempat lain, tetapi saya tidak ingat di mana. Mungkin semua disalin dari BCPL.
Steve314
6
unless(condition) {
  // ...
}

melakukan hal yang sama seperti:

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

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

melakukan hal yang sama seperti:

do {
  // ...
} while(!condition)
missingfaktor
sumber
Anda mungkin ingin pergi ke Lisp ...
duros
1
Atau Ruby, ini memiliki sintaks yang sama untuk unless.
Josh K
2
Terlihat cukup baik. Ada lebih dari satu cara untuk melakukannya.
2
@ Steve314 Anda harus menggunakan gaya penyangga yang salah . ;-)
Orbling
1
@Orbling - tidak sama sekali. Semua orang menggunakan gaya penyangga yang salah.
Steve314
5

Pada catatan yang berbeda, saya ingin melihat dukungan yang lebih baik untuk iterator dalam bahasa pemrograman. Khususnya, untuk saat Anda ingin turun dua koleksi berpasangan :

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

Beberapa bahasa dinamis mungkin sudah memiliki ini, atau dengan mudah mendukung melalui perpustakaan dan makro, tetapi saya pikir ini adalah semangat pertanyaan Anda.

Jika kedua set ukurannya tidak sama, maka bisa melempar pengecualian atau Anda bisa memiliki elsesetelah loop untuk memberi sinyal ada perbedaan ukuran.

Secara alami, Anda bisa menggeneralisasi ini untuk turun tiga atau lebih daftar.


Pembaruan: Berguna juga untuk melakukan produk Cartesian antar iterables:

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

yang tidak lebih dari loop bersarang:

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

Saya sedikit khawatir bahwa antara dua notasi yang saya berikan di sini bahwa ada perbedaan O (n) dan O (n ^ 2) dalam jumlah pasangan, dengan hanya perubahan satu karakter.

Macneil
sumber
2
Dalam Python ada zip dan zip_longest yang melakukan ini.
pembuat pil
Keren, mungkin saya meremehkan Python dan harus melihatnya kembali setelah bertahun-tahun. Itu mengingatkan saya, kadang-kadang Anda menginginkan produk Cartesian juga, setara dengan loop.
Macneil
1
Kedua kasus ini dalam Scala: paste.pocoo.org/show/297429
missingfaktor
1
Mengacu pada produk Cartesian: Sekali lagi, Python memilikinya. for a, b, c in itertools.product(iter1, iter2, iter3):memberi Anda produk Cartesian yang dievaluasi dengan malas. Apa itu? Anda ingin permutasi dan kombinasi dari iterator yang diberikan juga? itertools.permutations, itertools.combinations.
aaronasterling
1
Perspektif Haskell: gunakan "zipWith" untuk kasus pertama dan pemahaman daftar atau daftar monad untuk yang kedua. Seperti exmaples Python / Scala, tetapi lebih elegan. :)
LennyProgrammers
5

Ada yang disebut "Dijkstra's Loop" (juga disebut "Dijkstra's Guarded Loop"). Itu didefinisikan dalam The Guarded Command Language (GCL) . Anda dapat menemukan beberapa informasi tentang sintaks dan semantik di artikel Wikipedia di atas di bagian 6 Pengulangan: lakukan .

Saat ini saya benar-benar tahu satu bahasa pemrograman yang mendukung struture kontrol ini secara langsung. Ini adalah Oberon-07 (PDF, 70 KB). Dan itu mendukung "Dijkstra's Loop" dalam bentuk pernyataan sementara. Lihatlah bagian 9.6. Sedangkan pernyataan dalam PDF di atas.

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

PS Ini adalah salinan jawaban SO saya .

Kucing garong
sumber
Sepertinya model checker Spin juga memiliki konstruk ini, dengan semantik identik dan sintaksis dasarnya identik.
j_random_hacker
4

Ekspresi gaya ikon dengan backtracking bawaan.

Python mendapatkan banyak manfaat generator Ikon - dan melakukan pekerjaan yang lebih baik secara umum, IMO. Dan pada prinsipnya backtracking itu hanya semacam lemparan pengecualian, tapi itu adalah kesederhanaan dari ekspresi yang setara dengan ...

x = (a / b) else c;

untuk menangani kasus gagal seperti pembagian dengan nol.

Di mana Icon menjadi gila - tidak ada operator pembanding yang mengembalikan boolean. Perbandingan selalu berhasil atau memicu kemunduran, dan ada beberapa masalah semantik lain yang sekarang saya dengan susah payah mencoba untuk mengingat bahwa ... well, anggap saja itu mungkin lebih ditekan daripada terlupakan.

Saya selalu berpikir mereka harus memiliki ifekspresi tanpa bagian lain - if (condition, success-value)semacam itu, mundur jika kondisinya kembali salah - dan jatuhkan perbandingan aneh.

EDIT saya ingat - jelas banget. Perbandingan dengan dua argumen berhasil atau gagal - tidak menghitung nilai baru untuk kembali. Jadi ketika itu berhasil, apa yang itu kembali? Jawab - salah satu argumen. Tetapi jika Anda menulis a > b, yang merupakan argumen logis untuk kembali - aatau b? Dan bagaimana jika Anda menulis b < a? Saya pikir itu selalu mengembalikan argumen yang benar, yang masuk akal seperti apa pun, tetapi biasanya masih tampak seperti argumen yang salah bagi saya.

Steve314
sumber
4

Ini hanya ide dan sintaksis umum:

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

Kondisi JUGA selalu dievaluasi. ELSE bekerja seperti biasa.

Ini berfungsi untuk kasus juga. Mungkin itu adalah cara yang baik untuk menghilangkan pernyataan break:

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

dapat dibaca sebagai:

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

Saya tidak tahu apakah ini berguna atau mudah dibaca tetapi ini adalah contoh.

Maniero
sumber
3

Continuation Passing Style muncul di pikiran. Kemudian, tentu saja, Anda juga ingin memiliki Optimasi Panggilan Ekor .

pembuat pil
sumber
1
Bukan penggemar berat ini, dan saya tidak percaya itu benar-benar "struktur kontrol" tetapi lebih merupakan blok bangunan dalam bahasa fungsional dan gaya pemrograman. Node.js tampaknya agak ketagihan.
Josh K
1
Tentu saja itu adalah struktur kontrol. Hanya saja bukan yang datang dengan kata kunci seperti 'jika' atau 'untuk', tetapi sebagai pola untuk struktur aliran kontrol (karenanya, struktur kontrol). Itu bahkan digunakan di belakang layar oleh banyak kompiler. Dan itu tidak terbatas pada FLs juga. Anda membutuhkan fungsi sebagai Objek Kelas Pertama.
pembuat pil KB
1
Anda mendapatkan optimasi panggilan ekor dalam C dan C ++ hari ini, tetapi IMO itu tidak tepat sasaran. Intinya adalah bahwa hal itu adalah optimasi. Dalam Skema, panggilan ekor asli jelas. Dalam C ++ khususnya, banyak hal bisa berarti panggilan ekor Anda bukan panggilan ekor. Dan stack overflow berarti aplikasi Anda rusak. IMO, harus ada sesuatu seperti goto return ...;pernyataan, membuat maksud untuk tail-call eksplisit, jadi jika kompiler tidak dapat membuatnya iteratif itu adalah kesalahan.
Steve314
1
@ Macneil - yang saya tahu pasti, optimasi panggilan ekor dilakukan dalam GCC, Dentang dan Visual C ++. GCC memiliki konversi yang lebih canggih dari rekursi menjadi iterasi, yang dapat menangani sejumlah kasus yang bukan rekursi ekor. Tetapi banyak yang bisa salah. Berikan pointer ke variabel lokal di tail tail dan frame stack tidak dapat dihilangkan, karena variabel tersebut harus tetap hidup. Dalam C ++, destruktor variabel lokal biasanya akan terjadi setelah panggilan "tail" kembali, yang berarti itu bukan panggilan ekor sama sekali.
Steve314
1
@ Mike - itu maksud saya. Jika Anda menggunakan gaya pengkodean rekursif, tanpa "optimisasi" panggilan ekor, kode Anda berpotensi rusak, karena stack overflow adalah kesalahan. Dalam C ++ ini merupakan optimasi - bagi kompiler untuk melakukan optimisasi sehingga Anda tidak harus baik-baik saja, tetapi Anda tidak dapat mengandalkannya. Jika Anda ingin kebebasan untuk menulis dalam gaya rekursif, tetapi tidak ingin harus khawatir tentang masalah kedalaman tumpukan, penghapusan panggilan ekor bukan optimasi - ini masalah kebenaran. Jika rekursi adalah cara terbaik untuk mengkodekan sesuatu, Anda harus bisa melakukan itu - tidak perlu khawatir tentang stack overflow.
Steve314
3

Percabangan utas yang mulus, memiliki sintaksis seperti fungsi, tetapi dijalankan dalam utas yang terpisah dan tidak dapat mengakses data yang pada awalnya tidak diteruskan.

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

Ketika cabang dipanggil, ia akan segera mengembalikan pegangan.

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

Pegangan dapat digunakan untuk memeriksa apakah tugas sudah selesai.

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

Jika hasilnya diminta sebelum eksekusi selesai, utas utama hanya akan menunggu.

[result, storage]=handle.result()

Ini tidak akan mencakup skenario multithreading yang lebih maju, melainkan menyediakan cara awal yang mudah diakses untuk memanfaatkan beberapa core.

aaaaaaaaaaaa
sumber
Lihatlah Cilk, ini adalah ekstensi C yang sangat bersih dan sederhana: en.wikipedia.org/wiki/Cilk . Saya tidak tahu apakah ia memiliki handle.finished()tes, tetapi spawndan synchanya itu yang Anda butuhkan untuk 90% tugas pemrograman paralel.
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

Blok FIRST dan THEN berjalan jika salah satu dari 3 kondisi dievaluasi menjadi true. Blok PERTAMA berjalan sebelum blok bersyarat dan LALU berjalan setelah blok bersyarat telah berjalan.

Bersyarat atau penulisan akhir ELSE berikut pernyataan PERTAMA dan KEMUDIAN independen dari blok ini.

Itu bisa dibaca sebagai:

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

Fungsi-fungsi ini hanyalah sebuah formulir untuk dibaca. Mereka tidak akan menciptakan ruang lingkup. Ini lebih seperti gosub / kembali dari Basic.

Kegunaan dan keterbacaan sebagai bahan diskusi.

Maniero
sumber
2

Terkadang saya menemukan diri saya menulis sebuah loop yang perlu melakukan sesuatu yang berbeda selama iterasi pertama. Misalnya, menampilkan tag <th> alih-alih tag <td>.

Saya menangani situasi ini dengan bendera boolean. Sesuatu seperti ini:

first = true

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

Tampaknya konyol untuk memeriksa nilai firstsetiap iterasi ketika itu sebagian besar salah.

Saya ingin memiliki opsi pengulangan untuk menentukan badan pengulangan yang berbeda pada iterasi pertama. Tidak perlu untuk variabel yang terpisah. Kode yang dikompilasi tidak perlu satu, juga, karena kode yang dihasilkan akan memiliki dua tubuh, satu untuk iterasi pertama dan satu untuk sisanya.

Barry Brown
sumber
Pertanyaan SO memiliki ide yang serupa, tetapi dengan operator "lalu" untuk digunakan pada nilai. Dengan begitu, Anda mungkin tidak memiliki kode duplikat. Misalnyaprint(out, first "<th>" then "<td>")
Macneil
1
Cara yang lebih baik adalah dengan memulai iterasi +1.
Josh K
1
Kasing umum adalah pengulangan dengan antar-penanganan, misalnya mencantumkan item dengan pemisah koma. Sebenarnya, itu if (!first) gimme-a-comma ();sama saja. Namun saya keberatan, jika Anda membungkusnya dengan benar, Anda akan berakhir dengan hal-hal seperti metode gabungan string Python - namun seringkali Anda memerlukan pola dasar, loop yang mendasarinya tidak perlu ditulis ulang sesering itu.
Steve314
Seperti yang dikatakan Josh, tentu saja, menarik item pertama dari loop adalah sah. Dalam kasus pemisah koma itu berarti kode duplikat, tetapi itu bisa menjadi panggilan fungsi yang digandakan. Secara pribadi, saya lebih suka inefisiensi if (!first), tetapi pengoptimal mikro dapat mengajukan keberatan prediksi cabang.
Steve314
1
@Barry Brown: Membuka gulungan iterasi pertama dari loop mungkin atau mungkin tidak lebih cepat dari memeriksa bendera boolean. Prediktor cabang yang layak akan salah duga paling buruk pada iterasi ke-2 pertama, saya perkirakan :) Saya lebih suka menggunakan if (!first)dan membiarkan kompilator pengoptimal memutuskan apakah loop body cukup kecil sehingga membuka gulungan dan menyingkirkan firstadalah kemenangan bersih.
j_random_hacker
1

[disalin dari jawaban saya sendiri di stackoverflow]


ignoring - Untuk mengabaikan pengecualian yang terjadi pada blok kode tertentu.

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

Dengan konstruk kontrol pengabaian, Anda bisa menulisnya lebih ringkas dan lebih mudah dibaca sebagai:

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

[Scala menyediakan ini (dan banyak konstruksi kontrol penanganan Pengecualian lainnya) di perpustakaan standarnya, dalam paket util.control. ]

missingfaktor
sumber
4
Pengecualian seharusnya tidak diabaikan.
Josh K
1
Kecuali bahwa, dalam konteks, pengecualian mungkin bukan kesalahan.
Steve314
1
@Josh, @Steve: Ada kasus di mana Anda ingin mengabaikan pengecualian. Lihat utas ini untuk beberapa kasus seperti itu.
missingfaktor
Pengecualian adalah peringatan bahwa ada sesuatu yang salah. Satu try..catchblok kosong adalah satu hal; itu memaksa Anda untuk mengenali kesalahan dan sengaja mengabaikannya; sementara melempar potongan kode di bawah pengabaian global dapat menyebabkan masalah ketika pengecualian tersebut dilemparkan, serta menyebabkan kebiasaan pemrograman yang buruk.
Josh K
@Josh - Baru saja menghapus dua komentar karena saya tidak berpikir jernih - tetapi harapan yang tinggi untuk yang satu ini. Jika pernyataan itu bersifat global, saya mungkin setuju - tetapi sepertinya struktur blok bagi saya. TKI seperti tryblok, kecuali daftar pengecualian yang ditangkap dan diabaikan di depan, bukan nanti. Itu bahkan bisa menjadi keuntungan keterbacaan - mis. Membiarkan pembaca tahu bahwa file yang hilang bukan kesalahan bahkan sebelum mereka membaca panggilan terbuka.
Steve314
1

Dari pada:

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

Lakukan dengan Python, atau sekarang dengan cara C # juga:

action = val2func[myEnum]
action()

Scala memiliki banyak fitur baru.

Akhirnya, bahasa seperti Clojure dapat diperluas untuk menyediakan fungsionalitas tambahan.

Pekerjaan
sumber
1
C juga bisa melakukan ini. Dan Pascal. Mungkin semua bahasa-bahasa lama 70an / 80an / 90an. Array fungsi menjadi array pointer fungsi, tapi itu bukan masalah besar. Di mana semakin mudah adalah ketika Anda memiliki fungsi anonim - Anda tahu, seperti di Lisp, ML, ...
Steve314
Steve314 - koreksi - ini adalah contoh kamus yang memetakan nilai apa pun ke suatu fungsi. Di sinilah hal-hal menjadi sedikit lebih bersih daripada kebanyakan hal dari 70-an / 80-an / 90-an bisa lakukan.
Ayub
1

Saya punya dua ide.

Seringkali saya menemukan bahwa saya mengulangi diri saya dalam catchbalok-balok. Ini dapat sedikit dibantu melalui metode ekstraksi, tetapi itu dapat menyebabkan kekacauan yang tidak perlu jika metode ini sangat singkat atau tidak layak metode. Jadi, akan lebih baik untuk membuat sarang catch:

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
 }

Dalam pemrograman web saya juga sering menemukan diri saya sering melakukan sesuatu seperti ini (ini bukan contoh nyata jadi jangan menganalisis kasus fiksi):

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

Dalam Javascript (well, ECMAScript, dan mungkin orang lain yang saya tidak kenal), karena nilai apa pun dapat dievaluasi sebagai suatu kondisi, ||dapat membantu.

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

Saya sangat suka tampilannya, dan saya berharap lebih banyak bahasa, khususnya beberapa di sisi server, memiliki dukungan untuk itu. (PHP dapat mengevaluasi apa pun sebagai suatu kondisi, tetapi mengubah seluruh ekspresi kondisional menjadi boolean alih-alih mempertahankan nilai. Saya tidak tahu tentang Python atau Ruby.) Ini bisa menjadi berat setelah tiga kasus atau lebih, tetapi jika Anda memiliki lebih banyak dari tiga kasus, Anda mungkin juga memiliki desain perangkat lunak yang buruk.

Nicole
sumber
Python melakukan sesuatu seperti || Anda evaluasi, tetapi ketika akhirnya mendapatkan x if c else ysintaks ekspresi kondisional , alasan utama yang terjadi adalah karena banyak ekspresi menggunakan semantik ini untuk ||dan &&secara halus buggy. IIRC kasus umum adalah nilai (seperti nol) yang valid untuk aplikasi yang sedang diperlakukan false, sehingga dibuang sehingga digunakan fallback yang tidak valid sebagai gantinya. Namun - lihat jawaban saya, WRT, bahasa pemrograman Icon, yang dapat memiliki ekspresi seperti get1() else get2() else default.
Steve314
1

Switch umum telah mengatakan di atas:

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

Dalam Haskell:

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

sumber
0

Dalam C # saya ingin menggunakan yang sederhana switch () { ... }, tetapi dapat diperluas dengan ekspresi seperti:

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;

}

Dan seterusnya. Sama dengan angka atau jenis lain (yang mendukung IComparable, IConvertible, ...)

Ini mungkin membuat kode saya lebih singkat dan mudah dibaca.

Jenius
sumber
Jatuh pada kasus-kasus adalah kejahatan yang diketahui, dan saya biasanya baik-baik saja tanpanya. Dan lompatan terlalu GOTOish untuk pemrograman waras. Tetapi memiliki ekspresi dan non-statika dalam kasus ini akan menjadi tambahan yang bagus.
CodexArcanum
0

Ini adalah pertanyaan yang menyenangkan, seperti yang dikatakan @Macneil.

Struktur kontrol favorit saya yang tidak biasa, yang saya (batuk sederhana) temukan, adalah eksekusi diferensial .

Ini memiliki kegunaan tertentu. Bagi saya, penggunaan yang luar biasa dalam pemrograman antarmuka pengguna, yang merupakan contoh dari masalah yang lebih umum dari mempertahankan data yang berlebihan dalam korespondensi. Di satu sisi, ada data aplikasi, dan di sisi lain, ada kontrol UI, yang harus disimpan dalam perjanjian. Ini kedengarannya seperti "mengikat" tetapi sebenarnya ada lebih banyak untuk itu.

Biasanya saya mengimplementasikannya dengan macro di C atau C ++. Dalam C # saya harus melakukannya dengan pernyataan yang mengembang. Itu menyakitkan, tetapi berhasil.

Setelah saya menerapkannya dalam hal Lisp macro, dan kemudian itu sangat bersih. Itu tidak memerlukan kehati-hatian dari pihak programmer. Saya bisa melakukan hal yang sama dalam bahasa terstruktur lain jika saya mengambil kesulitan untuk menulis parser lengkap dan kemudian menghasilkan semua hal yang benar. Itu proyek besar, dan saya belum melakukannya.

Mike Dunlavey
sumber
0

Struktur kontrol "tradisional" seperti fortentang mengendalikan orang yang bekerja, membuatnya tunduk pada ideologi korup dari elit kapitalis yang berkuasa. Itu sebabnya saya menggunakan struktur kontrol alternatif seperti ph0rsebagai gantinya. Ini seperti for, tetapi lebih radikal: Anda tidak akan ketahuan ph0rmengenakan jas dan dasi, semburkan BS perusahaan. ph0rtetap nyata, bung.

Perangi kekuatan!

j_random_hacker
sumber
0

forLoop paling sederhana-

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
}
Gulshan
sumber