以下を検討してください。
if(a == b or c)
ほとんどの言語では、これは次のように記述する必要があります。
if(a == b or a == c)
これは少し面倒で情報を繰り返します。
上記のサンプル構文は少し不格好ですが、アイデアを伝えるためのより良い方法があると確信しています。
より多くの言語がそれを提供しないのはなぜですか?パフォーマンスや構文の問題はありますか?
以下を検討してください。
if(a == b or c)
ほとんどの言語では、これは次のように記述する必要があります。
if(a == b or a == c)
これは少し面倒で情報を繰り返します。
上記のサンプル構文は少し不格好ですが、アイデアを伝えるためのより良い方法があると確信しています。
より多くの言語がそれを提供しないのはなぜですか?パフォーマンスや構文の問題はありますか?
回答:
構文の問題は、構文が必要であることです。
言語の構文が何であれ、その言語を使用する人々はそれを学習する必要があります。さもなければ、彼らはコードを見て、それが何をするか知らないという危険を冒します。したがって、言語が多くのケースを適切に処理する単純な構文を持っている場合、それは一般的に良いことだと考えられています。
特定の例では、中置演算子(2つの引数をとるが記述されている関数)を取り、Argument1 Operator Argument2
それを複数の引数に拡張しようとしています。中置演算子の重要なポイントは、演算子が2つの引数の間にあることです。に拡張し(Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)
ても、に比べて多くの明確さが追加されているようには見えませんEquals(Arg1,Arg2,...)
。Infixは、一般に、ユーザーが使い慣れている数学的規則をエミュレートするためにも使用されますが、これは代替構文には当てはまりません。
パーサーが1つまたは2つの別のプロダクションルールを使用して文法を処理する必要があるということを除いて、アイデアに関連する特定のパフォーマンスの問題はありません。これにより、インタープリター型またはJITコンパイル済み言語に多少の違いが生じる可能性がありますが、大きな違いではない可能性があります。
アイデアの大きな問題は、言語で特別なケースをたくさん作成することは悪いアイデアになる傾向があるということだけです。
.
ます。したがって、それらはとして記述されarg1 op (arg2, arg3)
ます。正確には美しくありませんが、その言語のコンテキストで一部の場所で必要です。
a == b or c
他の人が望んでa == b or c but not d
いる間、誰もが必要というわけではありません。IMOは、ユーティリティ関数/ライブラリが役に立ちます。
f().Equals(a,b,c)
; (var temp=f(); temp.Equals(a)||temp.Equals(b)||temp.Equals(c))
その構文は完璧であると評価できますが、それが評価されint[] arr = {a,b,c}; f().Equals(arr);
た場合、特に、呼び出しごとに新しい配列を作成する必要がある場合は、あまり良くありません。
それは問題ではないので、それを解決することは基本的にゼロの利益をもたらしますが、それを実装することは非ゼロのコストをもたらします。
既存の範囲ベースの関数など、事実上すべての言語が提供する関数は、a == b || a == c
カットされないサイズにスケーリングすれば、この状況で完全にうまく機能します。
in_array($a, [$b, $c, $d, $e, $f])
。:P
一部の言語にはそのような機能があります。たとえば、Perl6 では、2つの値の「重ね合わせ」であるJunctionsを使用できます。
if $a == any($b, $c) {
say "yes";
}
# syntactic sugar for the above
if $a == $b | $c {
say "yes";
}
ジャンクションを使用すると、一部の言語でコレクションに対してスカラー操作が分散するのと同じように、一連のデータに対する操作を非常に簡潔に表現できます。たとえば、numpyでPythonを使用すると、比較はすべての値に分散できます。
import numpy as np
2 == np.array([1, 2, 3])
#=> np.array([False, True, False], dtype=np.bool)
(2 == np.array([1, 2, 3])).any()
#=> True
ただし、これは選択されたプリミティブタイプに対してのみ機能します。
ジャンクションに問題があるのはなぜですか?ジャンクションの操作は含まれている値に分散するため、ジャンクションオブジェクト自体はメソッド呼び出しのプロキシのように動作します。これは、ダックタイピング以外のいくつかのタイプシステムが処理できるものです。
このようなジャンクションが比較演算子の周りの特別な構文としてのみ許可されている場合は、型システムの問題を回避できます。しかし、この場合、それらは非常に制限されているため、適切な言語に追加するのに十分な価値がありません。同じ動作は、集合演算を使用して、またはすべての比較を手動でスペルアウトして表現することができます。ほとんどの言語は、すでに完全に細かい解決策がある場合、冗長な構文を追加するとは考えていません。
2 in [1, 2, 3]
。一方、numpyにa .all()
または何かがある場合、同等のプレーンpythonはそれほど簡潔ではありません。
==
演算子を使用して<
いましたが、代わりに使用することもできます-あなたのin
今はどこですか?ジャンクションは、メンバーシップテストの設定よりも一般的です。ジャンクションに対する操作(x|y).foo
はx.foo|y.foo
、ジャンクションが最終的に単一の値に折りたたまれるまで、すべてのメンバーに分散されるためです。提供されているNumPyコードは、プリミティブ型を想定して、Perl6ジャンクションの正確に同等ですがより詳細な変換を示しています。
一部の(人気のある)言語では、==
演算子は推移的ではありません。例えばJavaScriptで0
の両方に等しく、''
そして'0'
、その後''
そして'0'
お互いに等しくありません。PHPのそのような癖の詳細。
それはそれは意味しa == b == c
、それはそれはと解釈されますかどうかに応じて異なる結果をもたらす可能性があるため、別のあいまいさを追加します(a == b) & (a == c)
か(a == b) & (a == c) & (b == c)
。
ほとんどの言語では、これはIn
関数を書くことによって簡単に達成できるはずです。なぜそれを実際の言語の一部にするのですか?
たとえば、LinqにはがありContains()
ます。
了解しました。みなさん、C#での実装は次のとおりです。
public static bool In<T>(this T obj, params T[] values)
{
for(int i=0; i < values.Length; i++)
{
if (object.Equals(obj, values[i]))
return true;
}
return false;
}
a == b || a == c
複数回書いていることに気づいたら、たぶん今がその時ですequals_any(a, {b, c})
if (a > (b or c))
、およびのようなものをカバーするように簡単に拡張することはできませんif (a mod (b or c) == 2)
。
i
変数はありません。そして、全体的には長い一日を過ごした後に書かれているようです:)両方return true
とreturn false
ここのループの中に置くことは、最初の反復を超えてそれを作る方法がないことを意味するからです。あなたは最初のものと比較しているだけですvalue
。ところで、Any
@ Bobの提案どおりに使用して、次のように簡略化してみませんかreturn values.Any(value => Object.Equals(obj, value));
「if(a == b or c)」は、ほとんどの言語で機能します。a== bの場合、またはcが負、null、またはゼロでない場合。
それが冗長だと不平を言うのは要点を逃しています:あなたは条件に何十ものものを積み重ねるべきではありません。1つの値を他の任意の数の値と比較する必要がある場合は、サブルーチンを作成します。
c
評価がブール値であれば、ほとんどすべての言語で処理できますa == b || c
:)
if(a == b or c)
。私は休憩をとる必要があると思います...:P
if (a == b or c)
かどうかを確認するための擬似コードであるa
ISに等しいb
、またはa
等しくされますc
。それがc
ゼロでないことを確認することを意図していません。
通常、構文を最小限に抑え、代わりにそのような構成を言語自体で定義できるようにします。
たとえば、Haskellでは、2つ以上の引数を持つ任意の関数を、バッククォートを使用して中置演算子に変換できます。これはあなたが書くことを可能にします:
if a `elem` [b, c] then ... else ...
ここで、elem
第一の第二の要素であるかどうかをチェックする-値および値のリスト-普通の関数は2つの引数を取っています。
and
代わりに使用したい場合はどうなりor
ますか?Haskellでは、コンパイラベンダーが新しい機能を実装するのを待つ代わりに、次のものを使用できます。
if all (== a) [b, c] then ... else ...
一部の言語ではこれを提供しています-ある程度まで。
多分あなたの特定の例ではないかもしれませんが、例えばPythonの行を考えてみましょう:
def minmax(min, max):
def answer(value):
return max > value > min
return answer
inbounds = minmax(5, 15)
inbounds(7) ##returns True
inbounds(3) ##returns False
inbounds(18) ##returns False
したがって、いくつかの言語は、正しく表現している限り、複数の比較で問題ありません。
残念ながら、これは比較のために期待するようには機能しません。
>>> def foo(a, b):
... def answer(value):
... return value == a or b
... return answer
...
>>> tester = foo(2, 4)
>>> tester(3)
4
>>> tester(2)
True
>>> tester(4)
4
>>>
「Trueまたは4を返すとはどういう意味ですか?」-あなたの後の採用
この場合の解決策の1つは、少なくともPythonでは、少し異なる方法で使用することです。
>>> def bar(a, b):
... def ans(val):
... return val == a or val == b
... return ans
...
>>> this = bar(4, 10)
>>> this(5)
False
>>> this(4)
True
>>> this(10)
True
>>> this(9)
False
>>>
編集:次もPythonで同様のことを行います...
>>> def bar(a, b):
... def answer(val):
... return val in (a, b)
... return answer
...
>>> this = bar(3, 5)
>>> this(3)
True
>>> this(4)
False
>>> this(5)
True
>>>
したがって、どの言語を使用していても、それができないわけではなく、最初にロジックが実際にどのように機能するかを詳しく調べる必要があります。通常、それはあなたが何を言っているかを知ることの問題であり、あなたが何を言っているかを実際に言語に尋ねます。
Arrayで使用されるindexOfメソッドは、ほとんどすべての言語で使用されており、他のいくつかの値と値を比較できるため、特別な演算子はあまり意味がありません。
次のように書くJavaScriptでは:
if ( [b, c].indexOf(a) != -1 ) { .... }