どの有用な代替制御構造を知っていますか?[閉まっている]


12

同様の質問がSOで終了しました。

プログラミングをしているときに、特定の制御構造が非常に役立つことがありますが、プログラミング言語では直接利用できないことがあります。

計算を整理するのに便利な代替制御構造は何だと思いますか?

ここでの目標は、チャンキングと推論を改善するために、コードの構造化についての新しい考え方を獲得することです。

現在利用できない希望的な構文/セマンティックを作成するか、既存のプログラミング言語であまり知られていない制御構造を引用することができます。

回答は、新しいプログラミング言語や実際の言語を強化するためのアイデアを提供するものでなければなりません。

これはブレーンストーミングと考えてください。だから、おかしなアイデアだと思われるものを投稿してください。

それは命令型プログラミングについてです。


1
なぜこの質問は「命令型プログラミング」に関するものでなければならないのですか?
missingfaktor

@missingfaktor:制御構造は命令型プログラミングに関するものだからです。もちろん、機能的なアプローチや別の方法で解決できる問題もありますが、他のパラダイムでは制御構造が開発の中心に置かれていません。しかし、とにかくあなたは創造的です。
マニエロ

3
まあ、私はガードとパターンマッチングを共有するつもりでした、それらはより一般的であるため、CaseステートメントとIf-Thensですが、これがFPゾーンでない場合、それは私たちの残りのための単なるパターンマッチングです!
CodexArcanum

@CodexArcanum:さて、パターンマッチングは命令型の構造に非常によく似た構造です。実際、パターンマッチング自体は、命令型制御構造の代替です。恥ずかしがらないでください;-)
マニエロ

すべての答えを見ることで、現実の生活にはどの提案も存在しないことを嬉しく思います(できれば決して望みません)。申し訳ありません:)
セルグ

回答:


14

OK、これは楽しい質問です。

またelse最初のテストで条件が真ではない場合の一般的なfor whileループとforループが必要です。

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

これにより、条件の厄介な再計算や変数への保存が回避されます。


Pythonにはこれがあります。
バリーブラウン

おい!最後に、私が同意する風変わりなPythonの選択!;
マクニール

5
いいえ。Pythonのfor / whileループのelse節は、ループが正常に終了した場合に実行されます。つまり、ループはbreakまたはreturnステートメントまたは例外によって終了しません。forループでは、ループされた要素のシーケンスが使い果たされた後にelse節が実行され、whileループでは、ループ条件が初めてFalseに評価された後に実行されます。
-pillmuncher

4
MacneilがそれをPHPに記述する方法で、構成を追加する要求がありwhile ... elseます。「ここに結果がある/結果がなかった」というのは、Webアプリではかなり一般的なイディオムだからです。
ディーンハーディング

1
@SnOrfus:彼は、while条件が満たされない場合にのみ実行するコードブロック(ループのブロックとは別)が必要です。Do-Whileは、while条件に関係なく、ループのコードブロック(個別のブロックではない)を1回実行します。
軍団

10

いくつかの回答を1つにまとめてみませんか?

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.

命令型言語での拡張可能な一般化されたフロー制御構造構文は、かなり便利で面白いでしょう。それが現れるまで、私はただLispか何かを使うと思います。


5
役に立たず、混乱します。面白くない、遅い。
ジョシュK

2
@ジョシュK:ええ、あなたは正しい。何だ、あなたは私が同意しないと思った?この答えは、笑わないように舌を噛んでいます。
ジョンパーディ

それが皮肉なことを意図していた場合、それは確かに成功しました!
ジョシュK

11
+1笑わせた。反復間でコードを実行するには、「between」句が必要です。
バリーブラウン

1
+1、しかしそれも必要seventh { ... }です。
j_random_hacker

7

関数としての制御構造。

私がしたいforifelsewhile、などの機能ではなく、特殊な構造であることを。

私がしたいreturntry/exceptgoto継続の誘導体であることを。

もちろん、これは特定の制御構造とは関係がなく、制御構造の一般的な見方、つまり制御構造のメタと関係があります。


2
継続は言語の重要な概念であり、多くの言語から除外するのには十分な理由があります。
デビッドソーンリー

私は同意しません。たforifelse、とwhile私はそれらの関数へのパラメータが遅延し、元の構造と同じように動作するために実行する必要があることを推測します関数として。遅延実行を行う機能があると便利です。
ワイリー博士の見習い

1
@David:それらが存在するからといって、それらを使用しなければならないわけではありません。通常のプログラマーは、使用しているものreturn、例外などを使用できます。しかし、今では、必要に応じて、エキスパートプログラマーのツールボックスに強力な追加ツールがあります。その上、私見言語は「馬鹿げている」べきではありません。言語には、専門知識の増加とCS知識の成長をサポートする能力が必要です。
Dietbuddha

1
@dietbuddha:(続き)継続が悪いと言っているのではなく、それらがヘビーウェイトであると言っています。さらに、継続があると、C ++の例外のように、言語の使用方法が強制的に変更される可能性があります。継続をサポートする言語とそうでない言語は、良い面でも悪い面でも異なります。
デビッドソーンリー

1
@ Steve314-類似点はありますが、longjmpは継続ではありません。継続により、状態全体(すべてのローカル、グローバル、およびスタック)が保存されます。longjmpはスタックポインターを保存するため、setjmpが使用されたスコープを超えてエスケープすると、フレームが存在しないため、セグメンテーション違反が発生します。保存する変数にもいくつかの制限があると思います。
dietbuddha

6

リンクされた記事は、ドナルド・クヌースのN + 1/2ループについて間違いなく正しく理解しています。C / C ++ / Javaで表現:

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

これは、ファイルから行または文字を読み取り、EOFに到達したかどうかをテストしてから処理するのに役立ちます。私はパターンfor(;;)..if(..)break;が現れるのを見るのに慣れており、それは私にとって慣用的です。(Knuthの記事を読む前に、Literate Programmingという本に転載されていましたが、これはかつて「wtf?」でした。)

Knuthはキーワードを提案しましたloop/while/repeat

loop:
  S;
while C:
  T;
repeat

どこSTゼロ個以上の一連の文のためのプレースホルダであり、Cブール条件です。Sステートメントがない場合はwhileループになり、Tステートメントがない場合はdoループになります。

このコンストラクト自体は、ゼロ個以上のwhile C句を許可することで一般化でき、無限ループを表現するのに最適であり、2つのチェックを必要とするまれな条件になります。

同じ記事で、Knuthは、(gotoを使用する代わりに)例外をスロー/キャッチするローカルバージョンになるシグナリングメカニズムを提案しました。

私のために?私は私が表現できるように、Javaは、末尾呼び出しの最適化をサポートしたい任意の必要に応じて一般的な制御構造を。


更新:多くのC / C ++ / Javaプログラマーが、次の条件で埋め込み割り当てを使用してこの問題を回避することを忘れていましたwhile

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

Knuthの構築物から用語を使用して、これが許容されるとき、SおよびC単一の式にまとめることができます。上記の埋め込み割り当てを見るのが嫌いな人もいれば、上記のものを見るのが嫌いな人もbreakfor (;;)ます。場合しかし、S及びCそのような場合のように、組み合わせることができないS複数のステートメントを有し、for (;;)繰り返しコードなし唯一の選択肢です。もう1つの方法は、単にSコードを複製することです。

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

Knuthのloop/while/repeat代替案ははるかに優れているようです。


その繰り返しrepeat-untilループは、Pascal ループによく似ています。
メイソンウィーラー

@Mason:違いは、1つだけではなく、ステートメントと条件を挿入できる場所が2つあることです。
マクニール

ああ、私は何が起こっているのかわかります。うん、...面白い
メイソンウィーラー

ANSI Basicにはdo while ... loop until-前提条件と事後条件の両方がオプションであり、1つのループで両方を使用したことを(漠然と)覚えています。あなたの中間条件には、Adaがありexit when ...;ます。主な利点if ... break;exit loopname when ...;、複数の(必ずしもすべてではない)ネストされたループを一度に終了するように記述できることです。おそらく、そのブレークよりもわずかに多く見えるでしょう。
スティーブ314

面白いこと。Adaにはまさにその機能があります。
ジョンR.ストローム

6

BCPL言語が持っていたvalueof表現、単一の式に一連の文を回すために使用することができます:

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

どこsome series of statementsにでもあることができ、全体がとvalueof評価されvます。

これは、Javaでthis()or を呼び出すための引数を計算する必要がある場合に便利ですsuper()(その前に何も起こらないことが必要です)。もちろん、別のメソッドを作成することもできますが、コンテキストに多くのローカル値を渡す必要がある場合は苦痛になるかもしれません。

final必要な変数に使用できる場合は、valueof匿名の内部クラスを使用してJavaで既に実行できます。

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

1
GCCにはこれに対する拡張機能があります- ({ statement1; statement2; ...; result-expr; })。私は他の場所でも似たようなものを見てきましたが、どこにいるか覚えていません。ただし、おそらくすべてがBCPLからコピーされたものです。
Steve314

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

以下と同じことをします:

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

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

以下と同じことをします:

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

あなたは...のLispに行きたいかもしれません
DUROS

1
または、Rubyの同様の構文がありunlessます。
ジョシュK

2
かなりPerlishに見えます。それを行うには複数の方法があります。

2
@ Steve314 不適切なブレーススタイルを使用する必要があります。;-)
10

1
@Orbling-まったくありません。他のすべてのは、間違ったブレーススタイルを使用します。
Steve314

5

別の注意として、プログラミング言語でのイテレーターのより良いサポートを見たいと思います。特に、ペアで 2つのコレクション下ろしたい場合:

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

いくつかの動的言語には既にこれがあるか、ライブラリとマクロを介して簡単にサポートされているかもしれませんが、これはあなたの質問の精神にあると思います。

2つのセットが同じサイズでない場合、例外をスローするかelse、ループの後にサイズの違いがあったことを通知することができます。

当然、これを一般化して、3つ以上のリストに進むことができます。


更新:また、反復可能オブジェクト間でデカルト積を実行すると便利です。

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

これはネストされたループにすぎません:

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

ここで提供した2つの表記法の間に、ペアの数にO(n)とO(n ^ 2)の違いがあり、単一の文字が変更されているだけであることを少し心配しています。


2
Pythonには、これを行うzipとzip_longestがあります。
pillmuncher

クール、多分私はPythonを過小評価しているので、何年も後に再検討してください。これは、ネストされたforループに相当するデカルト積も必要な場合があることを思い出させます。
マクニール

1
Scalaのこれらの両方のケース:paste.pocoo.org/show/297429
missingfaktor

1
デカルト積に関して:繰り返しますが、Pythonにはそれがあります。for a, b, c in itertools.product(iter1, iter2, iter3):遅延評価されたデカルト積を与えます。あれは何でしょう?特定のイテレータの順列と組み合わせも必要ですか?itertools.permutationsitertools.combinations
aaronasterling

1
Haskellパースペクティブ:最初のケースには「zipWith」を使用し、2番目のリストには内包表記またはListモナドを使用します。Python / Scalaの例に似ていますが、よりエレガントです。:)
LennyProgrammers

5

いわゆる「ダイクストラのループ」(「ダイクストラの保護ループ」とも呼ばれます)があります。これは、Guarded Command Language(GCL)で定義されました。上記のウィキペディアの記事のセクション6 Repetition:doで、構文とセマンティクスに関する情報を見つけることができます。

今日、私は実際にこの制御構造を直接サポートする1​​つのプログラミング言語を知っています。それはオベロン-07(PDF 70 KB)。また、whileステートメントの形式で「ダイクストラのループ」をサポートします。セクション9.6をご覧ください。上記のPDFのwhileステートメント。

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

PSこれは私の答えのコピーです。


モデルチェッカーSpinにも、同じセマンティクスと基本的に同じ構文を持つこの構造があります。
j_random_hacker

4

バックトラッキングが組み込まれたアイコンスタイルの式。

Pythonには、アイコンジェネレーターの多くの利点があります。一般的に、IMOのほうが優れています。そして原則として、バックトラックは一種の例外スローでしたが、式の単純さは大まかに相当しました...

x = (a / b) else c;

ゼロ除算などの失敗ケースを処理します。

Iconの要点-ブール値を返す比較演算子はありません。比較は常に成功するか、バックトラックをトリガーし、他のセマンティックの問題がありましたが、今それを覚えようと必死にしています...まあ、それはおそらく忘れられているよりも抑圧されていると言いましょう。

私はいつもif、他の部分のない式があるべきだと思っていました- if (condition, success-value)ある種のもの、条件がfalseを返した場合にバックトラックする-そして奇妙な比較を落とします。

編集 -私は覚えている-本当に明らか。2つの引数との比較は成功または失敗します-返す新しい値を計算しません。成功すると、何返されますか?回答-引数の1つ。しかし、あなたが書いた場合a > bのリターンへの論理的な引数である、 - aまたはb?そして、b < a代わりに書くとどうなりますか?私は考えてそれは常に何も同じくらいの意味となり、右引数を、返されたが、それはまだ通常、私に間違った引数のように思えました。


4

これは単なる一般的な考え方と構文です。

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

また、条件は常に評価されます。ELSEは通常どおり動作します。

ケースにも有効です。おそらくそれはbreakステートメントを削除する良い方法です:

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

次のように読むことができます:

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

これが役に立つか、読むのが簡単かはわかりませんが、これは一例です。


3

継続合格スタイルが思い浮かびます。それから、もちろん、Tail Call Optimizationも必要になります。


1
これの大ファンではなく、実際には「制御構造」ではなく、関数型言語とプログラミングスタイルのビルディングブロックであるとは思わない。ただし、Node.jsはかなり夢中になっているようです。
ジョシュK

1
もちろん、それは制御構造です。「if」や「for」などのキーワードが付属しているのではなく、制御フローを構造化するためのパターン(したがって、制御構造)です。多くのコンパイラーによって舞台裏でも使用されています。また、FLにも限定されません。ただし、ファーストクラスオブジェクトとしての関数が必要です。
-pillmuncher

1
最近では、CおよびC ++でテールコールの最適化が行われますが、IMOではポイントを逃しています。ポイントは、それ最適化であることです。Schemeでは、本物のテールコールは明らかです。特にC ++では、多くのことがテールコールがテールコールではないことを意味します。スタックオーバーフローは、アプリが破損していることを意味します。IMOは、goto return ...;明示的に末尾呼び出しを行うためのステートメントのようなものがあるはずです。そのため、コンパイラーが反復処理を実行できない場合はエラーになります。
Steve314

1
@Macneil-確かに、テールコールの最適化はGCC、Clang、およびVisual C ++で行われます。GCCには再帰から反復へのより洗練された変換があり、末尾再帰ではない多くのケースを処理できます。しかし、多くのことが間違っている可能性があります。そのテールコールでローカル変数にポインターを渡すと、変数を維持する必要があるため、スタックフレームを削除できません。C ++では、ローカル変数デストラクタは通常、「テール」コールが戻った後に発生します。つまり、テールコールはまったくありません。
Steve314

1
@マイク-それが私のポイントです。スタックオーバーフローはエラーであるため、末尾の呼び出し「最適化」なしで再帰コーディングスタイルを使用すると、コードが破損する可能性があります。C ++では最適化です-コンパイラーが最適化を行うため、必要はありませんが、それらに依存することはできません。再帰的なスタイルで自由に記述したいが、スタックの深さの問題を心配したくない場合、末尾呼び出しの除去は最適化ではありません-それは正確性の問題です。再帰が何かをコーディングする最良の方法である場合、それを行うことができるはずです-スタックオーバーフローを心配する必要はありません。
Steve314

3

シームレスなスレッド分岐。関数のような構文を持ちますが、別のスレッドで実行され、最初に渡されていないデータにアクセスできません。

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

ブランチが呼び出されると、すぐにハンドルが返されます。

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

ハンドルを使用して、タスクが完了したかどうかを確認できます。

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

実行が完了する前に結果が要求された場合、メインスレッドは単に待機します。

[result, storage]=handle.result()

これは、より高度なマルチスレッドシナリオをカバーするものではなく、複数のコアの利用を開始する簡単にアクセス可能な方法を提供します。


Cilkをご覧ください。C:en.wikipedia.org/wiki/Cilkの非常にクリーンでシンプルな拡張です。私はそれが持っているかどうかを知りませんhandle.finished()テストを、しかし、spawnそしてsync、あなたが並列プログラミング作業の90%に必要なすべてのです。
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つの条件のいずれかがtrueと評価された場合、FIRSTおよびTHENブロックが実行されます。最初のブロックは条件付きブロックの前に実行され、THENは条件付きブロックの実行後に実行されます。

FIRSTおよびTHENステートメントに続くELSE条件付き書き込みまたは最終書き込みは、これらのブロックから独立しています。

次のように読むことができます。

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

これらの関数は、読むための単なるフォームです。スコープを作成しません。これは、Basicからのgosub / returnのようなものです。

議論の問題としての有用性と読みやすさ。


2

私は時々、最初の反復中に異なることをする必要があるループを書いていることに気づきます。たとえば、<td>タグの代わりに<th>タグを表示します。

この状況はブールフラグで処理します。このようなもの:

first = true

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

firstほとんどの場合falseになるすべての繰り返しで値をチェックするのはばかげているようです。

最初の反復で別のループ本体を指定するためのループオプションが必要です。別の変数は必要ありません。生成されたコードには、最初の反復と残りの2つのボディがあるため、コンパイルされたコードにも1つは必要ありません。


SOの質問にも同様の考えがありますが、値に使用される「then」演算子があります。そうすれば、おそらく重複したコードはありません。例:print(out, first "<th>" then "<td>")
マクニール

1
より良い方法は、繰り返し+1を開始することです。
ジョシュK

1
一般的なケースは、コンマ区切りで項目をリストするなど、処理間でループすることです。厳密には、それif (!first) gimme-a-comma ();はですが、ほとんど同じことです。しかし、私が異議を唱えるのは-適切にラップすると、Pythonの文字列結合メソッドのようなものになります-しかし、基本的なパターンが必要な場合は、基になるループを頻繁に書き換える必要はありません。
Steve314

Joshが言うように、もちろん、ループから最初のアイテムを引き出すことは有効です。コンマ区切りの場合、コードが重複することを意味しますが、関数呼び出しが重複する可能性があります。個人的にはif (!first)、の非効率性を好みますが、マイクロオプティマイザーは分岐予測の異議を提起する可能性があります。
Steve314

1
@Barry Brown:ループの最初の反復を展開することは、ブール値のフラグをチェックするよりも速い場合とそうでない場合があります。まともな分岐予測子は、最悪の場合、最初の2回の繰り返しを誤って予測します:) if (!first)ループ本体が十分に小さく、展開して取り除くことがfirst正味の勝利であるかどうかを最適化コンパイラに決定させます。
j_random_hacker

1

[stackoverflowの私自身の回答からコピー]


ignoring -特定のコードブロックで発生する例外を無視する。

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

制御構造を無視すると、次のように簡潔かつ読みやすく記述することができます。

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

[Scalaは、これ(および他の多くの例外処理制御構造)を、util.controlパッケージの標準ライブラリで提供しています。]


4
例外は無視されるべきではありません。
ジョシュK

1
例外として、例外として、例外はエラーではない場合があります。
スティーブ314

1
@ Josh、@ Steve:例外を無視したい場合があります。そのような場合については、このスレッドを参照してください。
missingfaktor

例外は、何かが間違っている可能性があるという警告です。空のtry..catchブロックは一つのことです。エラーを認識し、意図的に無視するように強制します。グローバルな無視でコードのチャンクをスローすると、それらの例外がスローされたときに問題が発生したり、プログラミングの習慣が悪くなったりすることがあります。
ジョシュK

@ジョシュ-私はまっすぐに考えていなかったので、2つのコメントを削除しました-しかし、これに対する希望は高いです。その声明がグローバルなものである場合、私はおそらく同意します-しかし、それは私にはブロック構造のように見えます。IOWはtryブロックのようなものですが、キャッチする例外をリストし、後でではなく前もって無視します。それは読みやすさの利点になることもあります。たとえば、オープンコールを読む前であっても、欠落ファイルがエラーではないことを読者に知らせることができます。
Steve314

1

の代わりに:

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

Pythonで実行するか、C#でも実行します。

action = val2func[myEnum]
action()

Scalaには多くの新機能があります。

最後に、Clojureなどの言語を拡張して、追加の機能を提供できます。


1
Cもこれを行うことができます。そしてパスカル。おそらくこれらすべての古い70年代/ 80年代/ 90年代の言語。関数の配列は関数ポインターの配列になりますが、大したことではありません。あなたが知っている、Lispの、MLのように、... -それはあなたが匿名関数持っているときに簡単です取得する場所
Steve314

Steve314-修正-これは、値を関数にマッピングする辞書の例です。これは、70年代/ 80年代/ 90年代のほとんどのものよりも少しきれいになる場所です。
ジョブ

1

私には2つのアイデアがあります。

多くの場合、私はブロックで自分自身繰り返していることがわかりcatchます。これはメソッドを抽出することで多少助けになりますが、メソッドが非常に短い場合やメソッドに値しない場合、不要な混乱を引き起こす可能性があります。そのため、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
 }

Webプログラミングでは、次のようなことを頻繁に行うこともよくあります(これは実際の例ではないため、架空のケースを分析しないでください)。

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

Javascript(ECMAScript、および多分私が不慣れな他の人)では、どの値も条件として評価できるので||役立ちます。

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

私はそれがどのように見えるかが本当に好きで、特にサーバー側のいくつかの言語がそれをサポートしてくれることを望みます。(PHPは何でも条件として評価できますが、値を保持するのではなく、条件式全体をブール値に変換します。PythonやRubyについては知りません。) 3つのケースよりも、ソフトウェアの設計が悪い可能性もあります。


Pythonはあなたの||のようなことをします それは最終的にはその条件式を得たときの評価は、しかしx if c else y、構文を、起こった主な理由は、表現の多くがためにこれらのセマンティクスを使用しているためだった||&&微妙にバグだらけでした。IIRCの一般的なケースは、として扱われるアプリケーションに有効な値(ゼロなど)でしたfalse。したがって、代わりに無効なフォールバックが使用されるように破棄されました。しかし-私の答えWRTのアイコンプログラミング言語を参照してくださいget1() else get2() else default
Steve314

1

一般化されたスイッチは上記のとおりです:

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

Haskellの場合:

  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#switch () { ... }では、simpleを使用しますが、そのような式で拡張可能です:

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;

}

等々。数字や他のタイプでも同じです(サポートするのはIComparableIConvertible、...)

これにより、コードがより簡潔で読みやすくなります。


ケースのフォールスルーは既知の悪であり、私は一般的にそれなしで大丈夫です。そして、ジャンプは正気のプログラミングにはあまりにもGOTOishです。しかし、ケースに式と非静的を含めることは素晴らしい追加です。
CodexArcanum

0

@マクニールが言ったように、それは楽しい質問です。

私が(謙虚な咳)を発見した私のお気に入りの異常な制御構造は、差分実行ですです。

特定の用途があります。私にとって、圧倒的な使用はユーザーインターフェイスのプログラミングにあります。これは、対応する冗長データを維持するというより一般的な問題の例です。一方では、アプリケーションデータがあり、他方では、同意する必要があるUIコントロールがあります。これは「結合」のように聞こえますが、実際にはもっと多くのことがあります。

通常、CまたはC ++のマクロで実装します。C#では、ステートメントを手動で展開する必要があります。それは苦痛ですが、うまくいきます。

Lispマクロの観点からそれを実装したら、それはとてもきれいでした。プログラマー側の注意は必要ありませんでした。完全なパーサーを作成してすべての適切なものを生成するのに苦労した場合、他の構造化言語でも同じことを行うことができました。それは大きなプロジェクトであり、私はまだやっていません。


0

「伝統的な」制御構造とforは、働く人を制御し、支配する資本主義エリートの腐敗したイデオロギーに従わせることです。そのため、代わりに別の制御構造を使用しますph0r。のようなものforですが、より過激です。ph0rスーツとネクタイを着て、企業BSを噴き出すことはありません。 ph0r本当だよ

力と戦う!


0

最もfor単純なループ

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
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.