ある値を他の2つ以上の値と比較する機能を備えた言語がないのはなぜですか?[閉まっている]


10

以下を検討してください。

if(a == b or c)

ほとんどの言語では、これは次のように記述する必要があります。

if(a == b or a == c)

これは少し面倒で情報を繰り返します。

上記のサンプル構文は少し不格好ですが、アイデアを伝えるためのより良い方法があると確信しています。

より多くの言語がそれを提供しないのはなぜですか?パフォーマンスや構文の問題はありますか?


6
SQLは次のことを提供します:where A IN(B、C)
thursdaysgeek

4
私はそれを提供するか、それを提供できる言語を求めていませんでしたが、なぜより多くの言語がそれを提供しないのですか?パフォーマンスや構文の問題はありますか?
2014年

8
@thursdaysgeekの答えを一般化するには、ほとんどの言語で、通常、セット包含を使用してそれを行います。(または、リストまたはタプルの方が簡単な場合)。同じように機能し、潜在的にトリッキーな構文の問題を回避します。あなたの例から、「bまたはc」はセット「{b、c}」を意味しますか、それとも|または ?Pythonでは、「bまたはc」は「trueの場合はbの値、それ以外の場合はcの値」を意味します
Rob

4
基本的に、これは構文の問題です。当面の問題は、「b or c」と「b or'd with c」の違いを明確にする直観的な方法があることです。
YoungJohn、2014年

2
それは特別な場合にa == b or cはかなりハックであり、私見にもうまくいきません。

回答:


24

構文の問題は、構文が必要であることです。

言語の構文が何であれ、その言語を使用する人々はそれを学習する必要があります。さもなければ、彼らはコードを見て、それが何をするか知らないという危険を冒します。したがって、言語が多くのケースを適切に処理する単純な構文を持っている場合、それは一般的に良いことだと考えられています。

特定の例では、中置演算子(2つの引数をとるが記述されている関数)を取り、Argument1 Operator Argument2それを複数の引数に拡張しようとしています。中置演算子の重要なポイントは、演算子が2つの引数の間にあることです。に拡張し(Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)ても、に比べて多くの明確さが追加されているようには見えませんEquals(Arg1,Arg2,...)。Infixは、一般に、ユーザーが使い慣れている数学的規則をエミュレートするためにも使用されますが、これは代替構文には当てはまりません。

パーサーが1つまたは2つの別のプロダクションルールを使用して文法を処理する必要があるということを除いて、アイデアに関連する特定のパフォーマンスの問題はありません。これにより、インタープリター型またはJITコンパイル済み言語に多少の違いが生じる可能性がありますが、大きな違いではない可能性があります。

アイデアの大きな問題は、言語で特別なケースたくさん作成することは悪いアイデアになる傾向があるということだけです。


1
余談ですが、インフィックス演算子は単なるなしのメソッド呼び出しなので、Scalaには任意数の引数を持つインフィックス演算子があり.ます。したがって、それらはとして記述されarg1 op (arg2, arg3)ます。正確には美しくありませんが、その言語のコンテキストで一部の場所で必要です。
アモン

何についてif my_var in (a, b)それから?これは、仕事に適したツールを使用することの問題ではありませんか?

素晴らしい点。言語の構文は言語の必須要素である必要があり、その上にライブラリを構築します。言語が「役立つ」構文糖で乱雑になりすぎると、使いにくくなります。a == b or c他の人が望んでa == b or c but not dいる間、誰もが必要というわけではありません。IMOは、ユーティリティ関数/ライブラリが役に立ちます。
2014年

おそらく、必要なのは、メソッドが、任意の数の引数を持つ呼び出しを複数の呼び出しとして処理し、結果を何らかの方法で組み合わせるように指定できる方法です。もし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);た場合、特に、呼び出しごとに新しい配列を作成する必要がある場合は、あまり良くありません。
スーパーキャット2014年

6

それは問題ではないので、それを解決することは基本的にゼロの利益をもたらしますが、それを実装することは非ゼロのコストをもたらします。

既存の範囲ベースの関数など、事実上すべての言語が提供する関数は、a == b || a == cカットされないサイズにスケーリングすれば、この状況で完全にうまく機能します。


2
+1ですが、「実質的にすべての言語が提供する既存の範囲ベースの関数」を1つまたは2つ表示することで、答えが改善されると思います。したがって、この選択肢はより明確になります。
Avner Shahar-Kashtan 2014年

「基本的にはメリットがゼロですが、実装するとコストがゼロにならない」ことを証明できますか?
DarekNędza2014年

3
@DarekNędza後半は議論の余地がないはずです:すべての機能は熟考され、実装され、テストされ、文書化され、サポートされなければなりません。それらのステップはどれも、合理的な測定基準(人々の時間、機会費用、複雑さ、誰かがそれに取り組むために支払われた場合の金銭的費用など)のもとでは無料です。

@ AvnerShahar-Kashtan Agreed-私にとって、それがどのように見えるか、たとえば、java、sh、またはzshかは明らかではありませんか?さて、彼は「現代」の言葉を暗示しているかもしれません。グルーヴィー?
Volker Siegel

PHPでは、のようになりますin_array($a, [$b, $c, $d, $e, $f])。:P
cHao 2014年

6

一部の言語にはそのような機能があります。たとえば、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はそれほど簡潔ではありません。
イズカタ2014年

@Izkata私は特に集合演算を使用しませんでした。私の例では==演算子を使用して<いましたが、代わりに使用することもできます-あなたのin今はどこですか?ジャンクションは、メンバーシップテストの設定よりも一般的です。ジャンクションに対する操作(x|y).foox.foo|y.foo、ジャンクションが最終的に単一の値に折りたたまれるまで、すべてのメンバーに分散されるためです。提供されているNumPyコードは、プリミティブ型を想定して、Perl6ジャンクションの正確に同等ですがより詳細な変換を示しています。
アモン

2

マクロのある言語では、そのようなものがない場合でも簡単に追加できます。ラケットを検討する

(define-syntax-rule (equal-any? a b ...)
  (or (equal? a b) ...))
(equal-any? "a" "b" "a")
> #t

メタプログラミングのない他の言語では、おそらくそれをセット/リストのメンバーシップチェックとして再定式化できます。

if a ∈ {b, c}

2
最初の2つは、すべての引数が等しいかどうかをチェックします。OPは、最初の引数が次のいずれかと等しいかどうかを確認しようとしています。不思議なことに、3番目のスニペットはそれを尊重しています。

@delnan申し訳ありませんが私はものを誤解しました。編集しました。
フィル

2

一部の(人気のある)言語では、==演算子は推移的ではありません。例えばJavaScriptで0の両方に等しく、''そして'0'、その後''そして'0'お互いに等しくありません。PHPのそのような癖の詳細。

それはそれは意味しa == b == c、それはそれはと解釈されますかどうかに応じて異なる結果をもたらす可能性があるため、別のあいまいさを追加します(a == b) & (a == c)(a == b) & (a == c) & (b == c)


2

ほとんどの言語では、これは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;
}

これは、OPのコードが表現できるようなタプルではなく、実行時の値の範囲で動作します。
DeadMG

簡単だからといって、やらなければならないという意味ではないようです。その...建設を検討してください。これらの基本的な機能とアルゴリズムのすべてを常に手動で何度も何度も何度も記述する必要があるのはなぜですか?
2014年

5
@Zerothは、同じことを何度も書いているかもしれませんが、代わりに、言語が提供する抽象化メカニズムを使用する傾向があります。あなたがa == b || a == c複数回書いていることに気づいたら、たぶん今がその時ですequals_any(a, {b, c})
amon

「を含む」実装はif (a > (b or c))、およびのようなものをカバーするように簡単に拡張することはできませんif (a mod (b or c) == 2)
tobyink 2014年

1
誰かがペダントと言いましたか?:)これはforeachループなので、i変数はありません。そして、全体的には長い一日を過ごした後に書かれているようです:)両方return truereturn falseここのループの中に置くことは、最初の反復を超えてそれを作る方法がないことを意味するからです。あなたは最初のものと比較しているだけですvalue。ところで、Any@ Bobの提案どおりに使用して、次のように簡略化してみませんかreturn values.Any(value => Object.Equals(obj, value));
Konrad Morawski

1

「if(a == b or c)」は、ほとんどの言語で機能します。a== bの場合、またはcが負、null、またはゼロでない場合。

それが冗長だと不平を言うのは要点を逃しています:あなたは条件に何十ものものを積み重ねるべきではありません。1つの値を他の任意の数の値と比較する必要がある場合は、サブルーチンを作成します。


3
どの言語が「ほとんど」を構成していますか?
FrustratedWithFormsDesigner 2014年

1
@FrustratedWithFormsDesigner、まあ、c評価がブール値であれば、ほとんどすべての言語で処理できますa == b || c:)
Brian S

@BrianS:OPはリテラル構文を意味すると思いましたif(a == b or c)。私は休憩をとる必要があると思います...:P
FrustratedWithFormsDesigner 2014年

@FrustratedWithFormsDesigner Lisp!...えっ?... :)
Volker Siegel

3
これは本当に質問の要点を逃しています。if (a == b or c)かどうかを確認するための擬似コードであるaISに等しいb、またはa等しくされますc。それがcゼロでないことを確認することを意図していません。
hvd 2014年

1

通常、構文を最小限に抑え、代わりにそのような構成を言語自体で定義できるようにします。

たとえば、Haskellでは、2つ以上の引数を持つ任意の関数を、バッククォートを使用して中置演算子に変換できます。これはあなたが書くことを可能にします:

if a `elem` [b, c] then ... else ...

ここで、elem第一の第二の要素であるかどうかをチェックする-値および値のリスト-普通の関数は2つの引数を取っています。

and代わりに使用したい場合はどうなりorますか?Haskellでは、コンパイラベンダーが新しい機能を実装するのを待つ代わりに、次のものを使用できます。

 if all (== a) [b, c] then ... else ...

1
構文を最小限に抑えたいのはなぜですか?そこに起こっているトレードオフは正確には何ですか?裏付けのない議論をせずにそのような宣言をしないでください。;)
2014年

1

一部の言語ではこれを提供しています-ある程度まで。

多分あなたの特定の例ではないかもしれませんが、例えば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
>>> 

したがって、どの言語を使用していても、それができないわけではなく、最初にロジックが実際にどのように機能するかを詳しく調べる必要があります。通常、それはあなたが何を言っているかを知ることの問題であり、あなたが何を言っているかを実際に言語に尋ねます。


1

Arrayで使用されるindexOfメソッドは、ほとんどすべての言語で使用されており、他のいくつかの値と値を比較できるため、特別な演算子はあまり意味がありません。

次のように書くJavaScriptでは:

if ( [b, c].indexOf(a) != -1 ) { ....  }

0

あなたはなぜこれができないのかと尋ねます: if(a == b or c)

Pythonはこれを非常に効率的に、実際には、次のようにして最も効率的に行いsetます。

if a in set([b, c]):
    then_do_this()

メンバーシップテストの場合、 'set'は要素のハッシュが同じであることを確認し、次に等しいかどうかを比較するだけなので、要素bとcはハッシュ可能でなければなりません。そうでない場合、リストは直接等しいかどうかを比較します。

if a in [b, c]:
    then_do_this()

0

APLスタイルの言語では、1回の操作でスカラーをベクトルの各要素と比較できます。これにより、ブールベクトルが生成されます。例として、最小限の機能を備えたapl計算機incaオンライン通訳)を恥知らずに宣伝したいと思います。

   a<5
5 
   b<4
4 
   c<5
5 
   a=b c
0 1 

これを単一の値に減らすには、包括的、または合計してゼロ以外の値をチェックすることで実行できます。

   0!+/a=b c
1 
   c<6
6 
   0!+/a=b c
0

したがって、他の答えが言うように、問題は構文です。ある程度、構文の解決策見つかりましたが、配列のパラダイムを学習するために多額のコストがかかります。

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