質問

この言語は使用しないで 短絡評価?あの特典を利用しないのですか?

いたように、これまでとは違ったつながる可能性がある一部の公演。ホントのところはどうなの?なぜですか?


関連する質問 特典の利用短絡評価

役に立ちましたか?

解決

短絡評価を使用しない理由:

  1. 関数、プロパティGet、または演算子メソッドに副作用がある場合、動作が異なり、結果が異なるためです。これは、A)言語標準、B)言語の以前のバージョン、またはC)言語の一般的なユーザーのデフォルトの仮定と競合する可能性があります。これらがVBが短絡しない理由です。

  2. コンパイラーに、ユーザーが入力した順序ではなく、式、演算子、および部分式を適切に並べ替えて整理する自由を持たせることができます。これらがSQLの理由です。短絡しないようにします(少なくとも、SQLを使用するほとんどの開発者が考えているような方法ではありません)。したがって、SQL(および他のいくつかの言語)は短絡する可能性がありますが、暗黙的に指定した順序である必要はなく、決定した場合に限ります。

ここでは、<!> quot;自動で暗黙的な順序固有の短絡<!> quot;について質問していると仮定しています。これは、ほとんどの開発者がC、C ++、C#、Javaなどに期待するものです。 VBとSQLには、順序固有の短絡を明示的に強制する方法があります。しかし、通常、人々がこの質問をするとき、それは<!> quot; Do What I Meant <!> quot;です。質問;つまり、<!> quot;どうして欲しいのですか?<!> quot;のように、私が書いた順に自動的に短絡します。

他のヒント

考えられる利点の1つは、一部の操作に、予想される副作用が生じる可能性があることです。

例:

if (true || someBooleanFunctionWithSideEffect()) {
    ...
}

しかし、それは一般的に眉をひそめています。

Adaはデフォルトではこれを行いません。短絡評価を強制するには、and thenまたはor elseの代わりにandまたはorを使用する必要があります。

問題は、実際に速度が低下する状況があることです。 2番目の条件の計算が速く、最初の条件が<!> quot; and <!> quotについてほとんど常に真である場合。 <!> quot;または<!> quot;の場合はfalseで、追加のチェックブランチ命令は無駄です。ただし、分岐予測機能を備えた最新のプロセッサでは、そうではないことを理解しています。もう1つの問題は、コンパイラがたまたま second 半分が安価であるか、失敗する可能性があることを認識し、それに応じてチェックを並べ替えたい場合があることです(短絡動作が定義されている場合は実行できません) )。

2番目のテストに副作用がある場合、コードの予期しない動作につながる可能性があるという異議を聞いたことがあります。私見それは<!> quot; unexpected <!> quot;あなたの言語があまりよくわからない場合でも、これを主張する人もいます。

実際の言語設計者がこの問題について何に言おうとしているのか興味がある場合は、 Ada 83(元の言語)根拠

  

ブール式のオペランド   AやBなどは、   任意の順序。複雑さに応じて   用語Bの場合、   効率的(一部ではあるがすべてではない   マシン)   用語Aの値はTRUEです。この   ただし、最適化の決定です   コンパイラによって取得され、それは   これを仮定するのは間違っています   最適化は常に行われます。他の   表現したい状況   各条件の組み合わせ   条件を評価する必要があります   意味)前の場合のみ   条件が満たされています。これらの両方   物事は短絡で行われることがあります   制御フォーム...

     

Algol 60では、効果を得ることができます   による短絡評価のみ   条件式の使用   完全な評価が実行されます   さもないと。これはしばしば   従うのが面倒な構造...

     

いくつかの言語は、その方法を定義しません   ブール条件は   評価された。結果プログラムとして   短絡評価に基づいて   ポータブルではありません。これは明らかに   分離する必要性を示しています   短絡からのブール演算子   制御フォーム。

で私の例を見てくださいSQL Serverのブール演算子短絡。ブール短絡が使用されない場合にSQLの特定のアクセスパスがより効率的である理由を示します。私のブログの例では、ブール短絡に実際に依存すると、SQLで短絡を想定している場合にコードが破損することがありますが、なぜが最初に右側を評価するSQLであるという推論を読むと、これが正しいことがわかり、アクセスパスが大幅に改善されます。

ビルは、短絡を使用せず、より詳細に綴るという正当な理由を示唆しています。高度な並列アーキテクチャでは、制御パスの分岐に問題がある場合があります。

たとえば、NVIDIA <!>#8217; s CUDAアーキテクチャを使用します。グラフィックチップはSIMTアーキテクチャを使用しているため、同じコードが多数の並列スレッドで実行されます。ただし、これは、すべてのスレッドが毎回同じ条件分岐を取る場合にのみ機能します。 異なるスレッドが異なるコードパスを取る場合、評価はシリアル化されます<!>#8211;つまり、一部のスレッドは待機する必要がある一方で、他のスレッドは代替コードブランチを実行するため、並列化の利点は失われます。

ショートサーキットには実際にコードの分岐が含まれるため、CUDAなどのSIMTアーキテクチャではショートサーキット操作が有害になる可能性があります。

<!>#8211;しかし、ビルが言ったように、<!>#8217;はハードウェアの考慮事項です。 言語に関しては、<< >>#8217; dの質問に答える際に no を鳴らします。センス。

100回のうち99回と言いますが、パフォーマンスのために短絡演算子を好むでしょう。

しかし、それらを使用しない場所を見つけた2つの大きな理由があります。 (ちなみに、私の例はCにあり、<!> amp; <!> amp;および||は短絡で、<!> amp;および|はそうではありません。)

1。)最初のステートメントによって返される値に関係なく、ifステートメントで2つ以上の関数を呼び出す場合。

if (isABC() || isXYZ()) // short-circuiting logical operator
    //do stuff;

その場合、isXYZ()はisABC()がfalseを返す場合にのみ呼び出されます。しかし、isXYZ()が何であれ呼び出されることを望むかもしれません。

したがって、代わりにこれを行います:

if (isABC() | isXYZ()) // non-short-circuiting bitwise operator
    //do stuff;

2。)整数でブール演算を実行しているとき。

myNumber = i && 8; // short-circuiting logical operator

は必ずしも次と同じではありません:

myNumber = i & 8; // non-short-circuiting bitwise operator

この状況では、短絡演算子は必ずしも式全体を評価するわけではないため、実際には異なる結果を得ることができます。そして、それはブール演算にとって基本的に役に立たないものにします。そのため、この場合は、代わりに非短絡(ビット単位)演算子を使用します。

私がほのめかしたように、これらの2つのシナリオは私にとって本当にまれです。しかし、両方のタイプの演算子には実際のプログラミング上の理由があることがわかります。幸運なことに、今日のほとんどの人気言語には両方があります。 VB.NETにもAndAlsoおよびOrElseの短絡演算子があります。今日の言語が両方を持っていない場合、私はそれが時代遅れであり、プログラマを本当に制限していると思います。

右側を評価したい場合:

if( x < 13 | ++y > 10 )
    printf("do something\n");

x <!> lt;であるかどうかに関係なく、yをインクリメントしたい場合があります。 13.ただし、これを行うことに対する良い議論は、副作用のない条件を作成する方が、通常はプログラミングの方が良いということです。

ストレッチとして:

言語を(安全性を犠牲にして)超安全にしたい場合は、短絡評価を削除します。 「安全」なことが起こるまでに時間がかかる場合、タイミング攻撃が使用される可能性がありますそれを台無しにします。短絡評価では、実行にさまざまな時間がかかるため、攻撃の穴が開けられます。この場合、短絡evalを許可しなくても、より安全なアルゴリズムを書くのに役立ちます(とにかくタイミングタイミング攻撃)。

Ada プログラミング言語は、ショートサーキット( AND OR )、コンパイラーが構成を最適化し、場合によっては並列化できるようにします。また、短絡を明示的に要求する演算子( AND THEN OR ELSE )プログラマーが望むとき。このような二重のアプローチの欠点は、言語をもう少し複雑にすることです(同じ「両方をやろう!」静脈で行われた1000の設計決定により、プログラミング言語が全体的にLOTにより複雑になります;-)。 / p>

これが現在どの言語でも起こっていることだとは思いませんが、操作の両側を異なるスレッドにフィードすることはかなり興味深いでしょう。ほとんどのオペランドは、互いに干渉しないように事前に決定できるため、異なるCPUにハンドオフするのに適した候補になります。

この種の問題は、複数のブランチを評価して1つを選択する傾向のある高度な並列CPUで重要です。

ちょっと、少し伸びましたが、「なぜ言語を使うのか」と尋ねました...「言語をなぜ使うのか」ではありません。

言語の劣化が を使用しない短絡評価をします。に合っッ無駄文、そして、その他の国における店舗により評価して各チップ、oleドラッグドロップ、一考の結果、条件によって評価した。

その理由はこの言語、その他の同期データフロー型言語においての簡潔な構文について語る。各支店のニーズを計算しなければならないように、過去のいずれのバージョンが必要になった場合には将来のサイクルです。の言語を一手に引き受けることにより、関係ないですが、C関数の呼び出しからでも予告なくす).

に劣化に相当する

if (y <> 0) then 100/y else 100

代表的な初心者です。当部門によるゼロは回避しないが、100/yを評価してもサイクル時y=0になります。

短絡によりアプリケーションIEの動作が変わる可能性があるため:

if(!SomeMethodThatChangesState() || !SomeOtherMethodThatChangesState())

読みやすさの問題に有効だと思います。誰かが完全に明らかではない方法で短絡評価を利用する場合、メンテナーが同じコードを見てロジックを理解するのは難しい場合があります。

メモリが機能する場合、erlangは、標準および/または、andalso / orelseの2つの構造を提供します。これは、「はい、これは短絡であり、あなたもそうすべきだ」という意図を明確にします。

例として、メンテナーがこれらの行に出くわしたとしましょう:

if(user.inDatabase() || user.insertInDatabase()) 
    user.DoCoolStuff();

意図が&quot;ユーザーがデータベースに存在しない場合、そのユーザーを挿入することを認識するには数秒かかります;それがうまくいくなら、クールなことをしてください」

他の人が指摘しているように、これは実際に副作用で物事を行うときにのみ関連します。

パフォーマンスの問題については知りませんが、それを回避する(または少なくとも過度に使用する)可能性のある論点は、他の開発者を混乱させる可能性があることです。

副作用の問題についてはすでに素晴らしい回答がありますが、質問のパフォーマンスの側面については何も見ませんでした。

短絡評価を許可しない場合、パフォーマンスの問題は、結果が変わらない場合でも両側を評価する必要があることです。これは通常、問題ではありませんが、次の2つの状況のいずれかで関連する可能性があります。

  • コードは非常に頻繁に呼び出される内部ループにあります
  • 式の評価に関連するコストが高い(おそらくIOまたは高価な計算)

短絡評価は、式の一部の条件付き評価を自動的に提供します。

主な利点は、式が単純化されることです。

パフォーマンスは向上する可能性がありますが、非常に単純な式のペナルティも確認できます。

別の結果は、式の評価の副作用が影響を受ける可能性があることです。

一般に、副作用に依存することは良い習慣ではありませんが、特定のコンテキストでは、好ましい解決策になる可能性があります。

VB6は短絡評価を使用しません。新しいバージョンが使用するかどうかはわかりませんが、疑っています。これは、古いバージョンもそうではなかったからであり、VB6を使用したほとんどの人がそれが起こることを期待しておらず、混乱を招くからだと思います。

これは、スパゲッティコードを書いたnoob VBプログラマーから抜け出し、本当のプログラマーになるための私の旅を続けるのを非常に困難にしたものの1つです。

多くの回答が副作用について話しました。以下に、副作用のないPythonの例を示します。この例では、短絡により読みやすさが向上します。

for i in range(len(myarray)):
  if myarray[i]>5 or (i>0 and myarray[i-1]>5):
    print "At index",i,"either arr[i] or arr[i-1] is big"

短絡はmyarray [-1]にアクセスしようとしないことを保証します。これはPython配列が0から始まるため、例外を発生させます。もちろん、コードは短絡なしで書くことができます。

for i in range(len(myarray)):
  if myarray[i]<=5: continue
  if i==0: continue
  if myarray[i-1]<=5: continue
  print "At index",i,...

しかし、短絡バージョンの方が読みやすいと思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top