web-dev-qa-db-ja.com

ある値を他の複数の値と比較する機能を備えた言語がないのはなぜですか?

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

if(a == b or c)

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

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

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

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

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

10
Zeroth

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

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

特定の例では、中置演算子(2つの引数を取るが_Argument1 Operator Argument2_と記述されている関数)を取得し、それを複数の引数に拡張しようとしています。中置演算子の全体の要点は、演算子が存在する限り、2つの引数の間に演算子を置くことであるため、あまりうまく機能しません。 _(Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)_に拡張しても、Equals(Arg1,Arg2,...)を大幅に明確にしたようには見えません。 Infixは、一般に、ユーザーが使い慣れている数学的規則をエミュレートするためにも使用されますが、これは代替構文には当てはまりません。

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

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

24
psr

一部の言語にはそのような機能があります。例えば。 Perl6では、2つの値の「重ね合わせ」である Junctions を使用できます。

if $a == any($b, $c) {
    say "yes";
}

# syntactic sugar for the above
if $a == $b | $c {
    say "yes";
}

ジャンクションを使用すると、一部の言語でコレクションに対してスカラー操作が分散するのと同じように、一連のデータに対する操作を非常に簡潔に表現できます。例えば。 Python= numpyを使用すると、比較はすべての値に分散できます。

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

ただし、これは選択されたプリミティブタイプに対してのみ機能します。

ジャンクションに問題があるのはなぜですか?ジャンクションの操作は含まれている値に分散するため、ジャンクションオブジェクト自体はメソッド呼び出しのプロキシのように動作します。これは、ダックタイピング以外のいくつかのタイプシステムで処理できます。

このようなジャンクションが比較演算子の周りの特殊なsyntaxとしてのみ許可されている場合は、型システムの問題を回避できます。しかし、この場合、それらは非常に制限されているため、健全な言語に追加するのに十分な価値がありません。同じ動作は、集合演算を使用したり、すべての比較を手動で綴ったりすることで表現できます。ほとんどの言語は、すでに完全に細かい解決策がある場合、冗長な構文を追加するとは考えていません。

6
amon

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

既存の範囲ベースの関数など、事実上すべての言語が提供する関数は、a == b || a == cカットしません。

6
DeadMG

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

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

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

if a ∈ {b, c}
2
Phil

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

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

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

2
Konrad Morawski

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

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

1
Satanicpuppy

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

たとえば、Haskellでは、2つ以上の引数を持つ任意の関数を、バッククォートを使用して中置演算子に変換できます。これにより、次のように記述できます。

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

ここで、elemは2つの引数(値と値のリスト)を取る通常の関数であり、最初のものが2番目の要素であるかどうかをチェックします。

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

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

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

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

「あなたは何をしますmean 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
user112358

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

次のように書くJavaScriptでは:

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

あなたはなぜこれを行うことができないのかと尋ねます: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
Aaron Hall

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

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

0
luser droog