31

コンマ ‹,› がガード テストandではなくショートカットである理由に興味があります。andalso

私は自分自身を「C ネイティブ」と呼んでいるので、短絡ブール評価の欠点は見当たりません。

to_core実際に生成されるコードを確認するために、フラグを使用していくつかのテスト コードをコンパイルしました。コンマを使用すると、左側の値と右側の値が評価され、両方が and されていることがわかります。andalsoケースブロック内にケースブロックがあり、への呼び出しがありませんerlang:and/2

ベンチマーク テストは行いませんでしたが、andalsoバリアントの方が速いと断言できます。

4

4 に答える 4

29

過去を掘り下げるには:

  • 元々、ガードには,個別のテストのみがあり、左から右に評価されて、それ以上存在しなくなりガードが成功するか、テストが失敗してガード全体が失敗するかのいずれかでした。その後;、同じ節で代替ガードを許可するために追加されました。ガードがテストの前に a の両側を評価する場合,、途中で誰かが間違っていることになります。@Kayの例は、それらが本来あるべきように左から右に移動することを暗示しているようです。

  • ブール演算子は、ずっと後のガードでのみ許可されました。

  • andorxorおよびnotはブール演算子であり、制御を目的としていませんでした。これらはすべて正格で、算術演算子+-*および '/' のように、最初に引数を評価します。Cにも厳密なブール演算子が存在します。

  • 短絡制御演算子andalsoorelseは、一部のコードを簡素化するために後で追加されました。あなたが言ったように、コンパイラはそれらをネストされたcase式に展開するので、それらを使用してもパフォーマンスは向上せず、コードの利便性と明確さだけです。これにより、表示された結果のコードが説明されます。

  • 注意ガードには式ではなくテストがあります。andwhile usingとandalsois equal to ,usingorelseは と同等ではないことを意味する微妙な違いがあり;ます。これは別の質問に任せます。ヒント: 失敗がすべてです。

したがって、 と の両方andandalsoそれぞれの場所があります。

于 2011-05-17T15:52:53.093 に答える
8

アダム・リンドバーグのリンクは正しいです。コンマを使用すると、andalso を使用するよりも優れたビーム コードが生成されます。+to_asm フラグを使用して次のコードをコンパイルしました。

a(A,B) ->
    case ok of
        _ when A, B -> true;
        _ -> false
    end.
aa(A,B) ->
    case ok of
        _ when A andalso B -> true;
        _ -> false
    end.

生成する

{function, a, 2, 2}.
  {label,1}.
    {func_info,{atom,andAndAndalso},{atom,a},2}.
  {label,2}.
    {test,is_eq_exact,{f,3},[{x,0},{atom,true}]}.
    {test,is_eq_exact,{f,3},[{x,1},{atom,true}]}.
    {move,{atom,true},{x,0}}.
    return.
  {label,3}.
    {move,{atom,false},{x,0}}.
    return.

{function, aa, 2, 5}.
  {label,4}.
    {func_info,{atom,andAndAndalso},{atom,aa},2}.
  {label,5}.
    {test,is_atom,{f,7},[{x,0}]}.
    {select_val,{x,0},{f,7},{list,[{atom,true},{f,6},{atom,false},{f,9}]}}.
  {label,6}.
    {move,{x,1},{x,2}}.
    {jump,{f,8}}.
  {label,7}.
    {move,{x,0},{x,2}}.
  {label,8}.
    {test,is_eq_exact,{f,9},[{x,2},{atom,true}]}.
    {move,{atom,true},{x,0}}.
    return.
  {label,9}.
    {move,{atom,false},{x,0}}.
    return.

+to_core フラグで生成されたものだけを調べましたが、明らかに to_core と to_asm の間に最適化ステップがあります。

于 2011-05-17T10:02:50.917 に答える
5

ブール演算子「and」および「or」は、常に演算子の両側の引数を評価します。一方、C演算子&&および||の機能が必要な場合 (2番目の引数が必要な場合にのみ評価される場合。たとえば、 trueが最初の引数であることが判明するとすぐに「 trueorelse false」を評価したい場合、2番目の引数は評価されません。「使用済み) 「 andalso 」と「orelse」に移動します。

于 2011-05-21T14:31:29.887 に答える
5

歴史的な理由です。andは、Erlang 5.1 で導入された以前に実装さandalsoれていました (現在見つけられる参照はEEP-17のみです)。下位互換性のため、ガードは変更されていません。

于 2011-05-17T08:08:46.587 に答える