왜 더 많은 언어가 한 개 이상의 다른 값과 값을 비교할 수있는 능력이 없습니까? [닫은]


10

다음을 고려하세요:

if(a == b or c)

대부분의 언어에서 다음과 같이 작성해야합니다.

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

약간 번거롭고 정보를 반복합니다.

위의 샘플 구문이 약간 복잡하다는 것을 알고 있지만 아이디어를 전달하는 더 좋은 방법이 있다고 확신합니다.

더 많은 언어가 제공하지 않는 이유는 무엇입니까? 성능이나 구문 문제가 있습니까?


6
SQL 제공한다 : 어디 IN (B, C)
thursdaysgeek

4
언어를 제공하거나 제공 할 수있는 언어를 요구하지 않았지만 더 많은 언어를 제공하지 않는 이유는 무엇입니까? 성능이나 구문 문제가 있습니까?
Zeroth

8
@thursdaysgeek의 답변을 대부분의 언어로 일반화하려면 일반적으로 세트 격리로 수행하십시오. (또는 더 쉬운 경우 목록이나 튜플) 동일하게 작동하고 잠재적으로 까다로운 구문 문제를 피합니다. 귀하의 예에서 "b 또는 c"는 "{b, c}"집합을 의미하거나 || ? 파이썬에서 "b 또는 c"는 "참이면 b의 값, 그렇지 않으면 c의 값"을 의미합니다
Rob

4
본질적으로 이것은 구문 문제입니다. 당면한 문제는 "b 또는 c"와 "b 또는 c와 c"의 차이를 명확하게하는 직관적 인 방법을 사용하는 것입니다.
YoungJohn

2
특별한 경우에는 꽤 해 a == b or c키고 IMHO도 잘하지 못합니다.

답변:


24

구문 문제는 구문이 필요하다는 것입니다.

귀하의 언어가 어떤 구문을 가지고 있든지, 언어를 사용하는 사람들은 그 언어를 배워야합니다. 그렇지 않으면 코드를보고 코드의 기능을 모를 위험이 있습니다. 따라서 언어에 많은 경우를 깔끔하게 처리하는 간단한 구문이있는 경우 일반적으로 좋은 것으로 간주됩니다.

특정 예에서, 중위 연산자 (두 개의 인수를 사용하지만 작성된 함수)를 가져 와서 Argument1 Operator Argument2여러 인수로 확장하려고합니다. infix 연산자의 전체 요점은 연산자가 2 개의 인수 사이에 올바르게 놓여 있기 때문에 매우 깨끗하게 작동하지 않습니다. 로 확장 (Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)해도에 많은 명확성이 추가되지 않는 것 같습니다 Equals(Arg1,Arg2,...). Infix는 일반적으로 사람들이 잘 알고있는 수학적 규약을 에뮬레이션하는 데 사용되는데, 이는 대체 구문에는 해당되지 않습니다.

파서는 구문 분석 속도에 약간의 영향을 줄 수있는 다른 생산 규칙 또는 2 개의 문법을 처리해야한다는 것 외에는 아이디어와 관련된 특정 성능 문제가 없습니다. 이는 해석되거나 JIT 컴파일 된 언어에 약간의 차이를 만들 수 있지만 큰 차이는 없습니다.

이 아이디어의 더 큰 문제 는 언어에서 특별한 경우많이 만드는 것이 나쁜 아이디어 인 경향이 있다는 입니다.


1
옆으로 : 스칼라는 임의의 수의 인수를 가진 중위 연산자를 가지고 .있습니다. 그래서 그들은로 쓰여질 것 arg1 op (arg2, arg3)입니다. 정확히 아름답지는 않지만 그 언어의 맥락에서 어떤 곳에서는 필요했습니다.
amon

대해 if my_var in (a, b)다음? 이것이 작업에 적합한 도구를 사용하는 것에 대한 질문이 아닌가?

좋은 지적. 언어 구문은 언어의 필수 요소 여야하며 그 위에 라이브러리를 구축해야합니다. 언어가 "유용한"구문 설탕으로 너무 어수선하면 사용하기가 더 어려워집니다. a == b or c다른 사람이 원하는 동안 모든 사람이 필요한 것은 아닙니다 a == b or c but not d. 유틸리티 기능 / 라이브러리가 구출되는 IMO입니다.
Allan

아마도 필요한 것은 임의의 수의 인수를 가진 호출을 여러 호출로 처리하고 결과를 어떤 방식으로 결합했는지를 메소드가 지정할 수있는 수단 일 것입니다. 만약 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);되지 않으면, 특히 각 호출에 대해 새 배열을 작성해야하는 경우에는 좋지 않습니다.
supercat

6

문제가 아니기 때문에 해결하면 기본적으로 이점이 없지만 구현하면 비용이 들지 않습니다.

기존의 범위 기반 기능과 실제로 모든 언어가 제공하는 기능 a == b || a == c은 자르지 않는 크기로 확장되는 경우이 상황에서 완벽하게 작동 할 수 있습니다 .


2
+1이지만 "실제로 모든 언어가 제공하는 기존의 범위 기반 함수"중 하나 또는 두 개를 표시하면 대답이 향상 될 것입니다.
Avner Shahar-Kashtan

"기본적으로 이점이 없지만 구현하면 비용이 0이 아님"을 증명할 수 있습니까?
Darek Nędza

3
@ DarekNędza 후반부에는 논쟁의 여지가 없어야합니다 . 모든 기능은 생각, 구현, 테스트, 문서화 및 지원되어야합니다. 이러한 단계 중 어느 것도 합리적인 척도 (사람의 시간, 기회 비용, 복잡성, 누군가가 돈을 지불하는 경우 금전적 비용 등) 하에서 자유로울 수 없습니다.

@ AvnerShahar-Kashtan Agreed-나에게 그것이 어떻게 보일지, 분명하지 않은지, java 또는 sh 또는 zsh입니까? 그는 '현대'언어를 암시했을 수도 있습니다. 그루비?
Volker Siegel

PHP에서는 다음과 같습니다 in_array($a, [$b, $c, $d, $e, $f]). : P
cHao

6

일부 언어에는 그러한 기능이 있습니다. 예를 들어 Perl6에서는 Junctions 를 사용할 수 있습니다. 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

그러나 이것은 선택된 기본 유형에 대해서만 작동합니다.

접합부가 왜 문제가됩니까? 정션에 대한 작업은 포함 된 값으로 분산되므로 정션 오브젝트 자체는 메소드 호출을위한 프록시처럼 작동합니다. 오리 입력 외에는 몇 가지 유형 시스템 만 처리 할 수 ​​있습니다.

이러한 정션이 비교 연산자 주위의 특수 구문 으로 만 허용되면 유형 시스템 문제를 피할 수 있습니다 . 그러나이 경우에는 너무 제한되어 있으므로 제정신의 언어에 추가 될만큼 충분한 가치를 추가하지 못합니다. 동일한 동작이 set 연산을 사용하여 표현되거나 모든 비교를 수동으로 철자 할 수 있으며, 이미 완벽하게 훌륭한 솔루션이있는 경우 대부분의 언어는 중복 구문 추가를 믿지 않습니다.


이 특정 숫자 예제는보다 명확하게 다시 작성할 수 있습니다 2 in [1, 2, 3]. 반면에, numpy에 .all()무언가 가 있다면 , 동등한 일반 파이썬은 간결하지 않습니다.
이즈 카타

@Izkata 나는 특별히 집합 연산을 사용하지 않았습니다. 내 예제에서는 ==연산자를 사용 <했지만 대신 사용할 수도 있습니다. in현재 위치는 어디 입니까? 접합에 대한 작업은 모든 회원을 통해 배포하기 때문에 접합은, 세트 회원 테스트보다 더 일반적이다 - (x|y).foo이다 x.foo|y.foo, 접합 마침내 하나의 값으로 붕괴 될 때까지. 제공된 NumPy 코드는 기본 유형을 가정 할 때 Perl6 접합의 정확히 동일하지만 더 자세한 변환을 보여줍니다.
amon

2

매크로가있는 언어의 경우 아직없는 경우 쉽게 추가 할 수 있습니다. 라켓 고려

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

메타 프로그래밍이없는 다른 언어에서는 아마도 집합 / 목록 멤버쉽 검사로이를 재구성 할 수 있습니다.

if a ∈ {b, c}

2
처음 두 개는 모든 인수가 동일한 지 확인합니다. OP는 첫 번째 인수가 다음 중 하나와 같은지 확인하려고합니다. 흥미롭게도, 세 번째 스 니펫은이를 존중합니다.

@delnan 죄송합니다. 물건을 잘못 이해했습니다. 편집했습니다.
Phil Phil

2

일부 (인기있는) 언어에서 ==연산자는 전 이적이지 않습니다. 자바 스크립트의 예를 들어 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

쉬운 일이라고해서 그렇게해서는 안된다는 의미는 아닙니다. 그 ... 건설을 고려하십시오. 왜 우리가 항상 이러한 기본 기능과 알고리즘의 모든 부분을 반복해서 수동으로 작성해야합니까?
Zeroth

5
@Zeroth 어쩌면 당신은 같은 것을 반복해서 쓰고 있지만, 다른 사람들은 그들의 언어가 제공하는 추상화 메커니즘을 대신 사용하는 경향이 있습니다. 자신이 a == b || a == c여러 번 쓰는 것을 본다면 아마 그럴 시간입니다.equals_any(a, {b, c})
amon

"포함"구현은 if (a > (b or c))and와 같은 것을 다루기 위해 쉽게 확장되지 않습니다 if (a mod (b or c) == 2).
tobyink

1
누군가가 페달을 말했습니까? :) foreach 루프이므로 i변수 가 없습니다 . 당신이 긴 하루를 했어 후 :) 모두를 가하고 있기 때문에 전체가 기록 될 것으로 보인다 return truereturn false루프 내부의 것은 여기가 최초의 반복을 넘어 그것을 만들 것입니다 방법이 없습니다 것을 의미합니다. 첫 번째와 만 비교하고 value있습니다. 그건 그렇고, Anyreturn values.Any(value => Object.Equals(obj, value));
@Bob이

1

"if (a == b 또는 c)"는 대부분의 언어에서 작동합니다. a == b 인 경우 또는 c가 음수, 널 또는 0이 아닌 경우.

그것이 장황하다는 불만은 요점을 놓치고 있습니다. 조건부로 12 가지 물건을 쌓아서는 안됩니다. 하나의 값을 임의의 수의 다른 값과 비교해야하는 경우 서브 루틴을 빌드하십시오.


3
어떤 언어가 "가장 많이"구성됩니까?
FrustratedWithFormsDesigner

1
@FrustratedWithFormsDesigner, c부울로 평가 되면 거의 모든 언어가 처리 할 수 ​​있습니다 a == b || c:)
Brian S

@BrianS : OP가 리터럴 구문을 의미한다고 가정했습니다 if(a == b or c). 휴식을 취해야한다고 생각합니다 ... : P
FrustratedWithFormsDesigner

@FrustratedWithFormsDesigner Lisp! ... huh? ... :)
Volker Siegel

3
이것은 실제로 질문의 요점을 놓칩니다. if (a == b or c)있는지 확인하는 의사 코드이다 aIS 같 b거나 a같은지가 c. c0이 아닌 것을 확인하는 것은 아닙니다.
hvd

1

일반적으로 구문을 최소한으로 유지하고 언어 자체에서 이러한 구문을 정의 할 수 있습니다.

예를 들어, Haskell에서는 두 개 이상의 인수가있는 함수를 백틱을 사용하여 중위 연산자로 변환 할 수 있습니다. 이것은 당신이 쓸 수 있습니다 :

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

여기서 elem두 개의 인수 (값과 값 목록)를 취하는 일반 함수이며 첫 번째 요소가 두 번째 요소인지 확인합니다.

and대신에 사용하려면 or어떻게합니까? Haskell에서는 컴파일러 공급 업체가 새로운 기능을 구현할 때까지 기다리지 않고 다음을 사용할 수 있습니다.

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

1
왜 구문을 최소한으로 유지하고 싶습니까? 트레이드 오프는 정확히 무엇입니까? 지지하는 주장없이 그런 선언을하지 마십시오. )
제 0

1

일부 언어는이를 어느 정도 제공합니다.

어쩌면 구체적인 예는 아니지만 파이썬 라인을 예로 들어 보겠습니다.

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를 반환 한다는 것은 무슨 입니까?" -당신이 후 고용

이 경우 적어도 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
>>> 

편집 : 다음은 파이썬에서도 비슷한 일을 할 것입니다 ...

>>> 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 메소드는 다른 여러 언어와 값을 비교할 수 있으므로 특수 연산자가별로 의미가 없다고 생각합니다.

자바 스크립트에서는 다음과 같이 작성합니다.

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

0

왜 우리가 이것을 할 수 없는지 묻습니다. if(a == b or c)

파이썬은 실제로 이것을 가장 효율적으로 수행합니다 set:

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

멤버쉽 테스트의 경우 'set'은 요소의 해시가 동일한 지 확인한 다음 동등성을 비교하기 만하면 요소 b와 c는 해시 가능해야합니다. 그렇지 않으면 목록이 동등성을 직접 비교합니다.

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

0

APL 스타일 언어를 사용하면 한 번의 작업으로 스칼라를 벡터의 각 요소와 비교할 수 있습니다. 부울 벡터가 생성됩니다. 예를 들어, 나는 최소한의 기능을 갖춘 apl 계산기 인 잉카 ( 온라인 통역사 )를 부끄럽게 홍보하고 싶습니다 .

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

이 값을 단일 값으로 줄이려면 포괄적이거나 0이 아닌 값을 합산하여 확인하면됩니다.

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

다른 답변에서 알 수 있듯이 문제는 구문입니다. 어쨌든 배열 패러다임을 배우는 데 드는 막대한 비용으로 구문 솔루션 발견되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.