대부분의 주류 언어가 3-way 부울 비교를 위해“x <y <z”구문을 지원하지 않는 이유는 무엇입니까?


34

두 숫자 (또는 다른 잘 정렬 된 엔티티)를 비교하려면을 사용하십시오 x < y. 세 가지를 비교하고 싶다면 고등학교 대 수생이 시도해볼 것을 제안 x < y < z합니다. 그러면 프로그래머가 "아니요, 유효하지 않습니다 x < y && y < z. 해야합니다 "라고 응답합니다 .

내가 접한 대부분의 언어는이 구문을 지원하지 않는 것 같습니다. 수학에서 얼마나 자주 사용되는지는 이상합니다. 파이썬은 예외입니다. JavaScript 예외처럼 보이지만 실제로는 연산자 우선 순위와 암시 적 변환의 불행한 부산물입니다. Node.js를 년 1 < 3 < 2에 평가 true정말 때문에, (1 < 3) < 2 === true < 2 === 1 < 2.

그래서 내 질문은 이것입니다 : x < y < z예상되는 의미론을 가진 프로그래밍 언어에서 일반적으로 사용할 수 없습니까?


1
다음은 파이썬 문서에서 직접 작성하는 문법 파일입니다. 그렇게 어렵다고 생각하지 않습니다. docs.python.org/reference/grammar.html
Aaron Hall

나는 파이썬을 아는 것뿐만 아니라 다른 언어를 모른다. 그러나 나는 파이썬이 그것을 해석하는 단순함을 말할 수있다. 아마도 대답해야 할 것 같습니다. 그러나 나는 그것이 피해를 입는 것에 대한 gnasher729의 결론에 동의하지 않습니다.
Aaron Hall

@ErikEidt-수요는 우리가 고등학교 (또는 이전)에서 배운 방식으로 수학적 표현을 쓸 수있게되었습니다. 수학적으로 기울어 진 모든 사람들은 $ a <b <c <d $의 의미를 알고 있습니다. 기능이 존재한다고해서 반드시 사용해야하는 것은 아닙니다. 그것을 좋아하지 않는 사람들은 항상 사용을 금지하는 개인 또는 프로젝트 규칙을 만들 수 있습니다.
David Hammen

2
C # 팀이 (예를 들어) LINQ를 탐색하는 것이 낫고 앞으로 레코드 유형과 패턴 일치를 사용하여 사람들에게 4 가지 키 스트로크를 절약하고 실제로는하지 않는 구문 설탕을 추가하는 것보다 표현력을 추가하십시오 ( static bool IsInRange<T>(this T candidate, T lower, T upper) where T : IComparable<T>실제로 당신을보고 싶어하는 것처럼 도우미 메소드를 작성할 수도 있습니다 &&)
sara

1
SQL은 상당히 "주류"이며 "x와 1과 10 사이"를 쓸 수 있습니다
JoelFan

답변:


30

이진 연산자는 체인으로 연결될 때 일반적으로 자연스럽게 다음과 같은 추상 구문 트리를 생성합니다.

이진 연산자에 대한 일반적인 추상 구문 트리

평가 (잎에서 수행)하면에서 부울 결과가 생성 x < y되고 유형 오류가 발생 boolean < z합니다. 위해에 대한 x < y < z작업을하려면, 당신은 같은 구문 트리를 생성하는 컴파일러에 특별한 경우를 만들어야합니다 논의 :

특수한 경우 구문 트리

그렇게 할 수는 없습니다. 분명히 그렇습니다.하지만 실제로 자주 나오지 않는 경우 파서에 약간의 복잡성이 추가됩니다. 기본적으로 때때로 이진 연산자처럼 작동하고 때로는 삼항 연산자처럼 효과적으로 작동하는 기호를 만들고 있습니다. 오류 처리와 관련된 모든 영향이 수반됩니다. 따라서 언어 디자이너가 가능한 한 피하는 것이 잘못 될 수있는 공간이 많이 있습니다.


1
"그런 다음 부울 <z를 수행하려고하면 형식 오류가 발생합니다."-컴파일러가 z 비교에 대해 적절한 위치에서 y를 평가하여 체인을 허용하는 경우에는 해당되지 않습니다. "그러면 언어 디자이너가 가능한 한 피하는 것이 잘못 될 수있는 많은 공간이 추가됩니다." 실제로 파이썬은이 작업을 수행하는 데 아무런 문제가 없으며 파싱 논리는 단일 함수로 제한됩니다 : hg.python.org/cpython/file/tip/Python/ast.c#l1122- 갈 공간이 많지 않습니다. 잘못된. "때로는 이진 연산자처럼 작동하고 때로는 효과적으로 삼항 연산자처럼 작동합니다."파이썬에서 전체 비교 체인은 삼항입니다.
Aaron Hall

2
나는 그것이 불가능하다고 말한 적이 없으며 추가 복잡성을 가진 추가 작업입니다. 다른 언어는 작성하지 않아도 어떤 그들의 비교 연산자를 처리하기위한 별도의 코드를. 다른 바이너리 연산자와 함께 무료로 얻을 수 있습니다. 우선 순위 만 지정하면됩니다.
Karl Bielefeldt

네,하지만 ... 거기에 있다 이미 삼항 연산자 많은 언어에서 구매 가능?
JensG

1
@JensG 삼항의 의미는 3 개의 인수가 필요하다는 것을 의미합니다. 링크의 맥락에서 이는 삼항 조건 연산자입니다. 2를 취하는 것처럼 보이지만 실제로는 3을 취하는 연산자에 대해 용어 인 "일차적"인 것 같습니다.이 답변의 가장 큰 문제는 대부분 FUD입니다.
Aaron Hall

2
나는이 대답에 대한 downvoters 중 하나입니다. (@JesseTG :이 답변을 수락하지 마십시오.)이 질문은 무엇을 x<y<z의미 하는지 또는 더 중요한 것이 무엇인지 혼동합니다 x<y<=z. 이 답변 x<y<z은 삼항 연산자로 해석 됩니다. 이것이 바로이 잘 정의 된 수학적 표현이 해석되어서는 안되는 방법입니다. x<y<z대신 약칭입니다 (x<y)&&(y<z). 개별 비교는 여전히 이진입니다.
David Hammen

37

x < y < z프로그래밍 언어에서 일반적으로 사용할 수없는 이유는 무엇 입니까?

이 답변에서 나는 결론

  • 이 구문은 언어 문법으로 구현하기가 쉽지만 언어 사용자에게 가치를 창출하지만,
  • 이것이 대부분의 언어에 존재하지 않는 주된 이유는 다른 기능과 관련하여 언어의 중요성과 언어 관리 기관의 의지가 없기 때문입니다.
    • 잠재적으로 주요 변경 사항이있는 사용자를 화나게 함
    • 기능을 구현하기 위해 이동합니다 (예 : 게으름).

소개

이 질문에 대해 파이썬리스트의 관점에서 말할 수 있습니다. 이 기능을 가진 언어의 사용자이며 언어의 구현 세부 사항을 연구하고 싶습니다. 이 외에도 C 및 C ++ (ISO 표준은위원회가 관리하고 연도별로 버전이 지정됨)와 같은 언어를 변경하는 프로세스에 어느 정도 익숙하며 Ruby와 Python이 주요 변경 사항을 구현하는 것을 보았습니다.

파이썬의 문서와 구현

문서 / 문법에서 비교 연산자를 사용하여 여러 표현식을 연결할 수 있음을 알 수 있습니다.

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "!="
                   | "is" ["not"] | ["not"] "in"

그리고 문서에는 다음과 같이 명시되어 있습니다.

비교는 임의로 연결될 수 있습니다. 예를 들어, x <y <= z는 y가 한 번만 평가된다는 점을 제외하고 x <y 및 y <= z와 같습니다 (두 경우 모두 x <y가 발견 될 때 z는 전혀 평가되지 않음) 거짓).

논리적 동등성

그래서

result = (x < y <= z)

논리적으로 동등한 평가의 측면에서 x, y그리고 z제외한 y회 평가 :

x_lessthan_y = (x < y)
if x_lessthan_y:       # z is evaluated contingent on x < y being True
    y_lessthan_z = (y <= z)
    result = y_lessthan_z
else:
    result = x_lessthan_y

다시, 차이점은 y로 y를 한 번만 평가한다는 것입니다 (x < y <= z).

(괄호는 완전히 불필요하고 중복되지만 다른 언어에서 온 사람들의 이익을 위해 사용했으며 위의 코드는 합법적 인 Python입니다.)

구문 분석 된 추상 구문 트리 검사

파이썬이 체인 비교 연산자를 구문 분석하는 방법을 검사 할 수 있습니다.

>>> import ast
>>> node_obj = ast.parse('"foo" < "bar" <= "baz"')
>>> ast.dump(node_obj)
"Module(body=[Expr(value=Compare(left=Str(s='foo'), ops=[Lt(), LtE()],
 comparators=[Str(s='bar'), Str(s='baz')]))])"

따라서 파이썬이나 다른 언어로는 파싱하기가 어렵지 않다는 것을 알 수 있습니다.

>>> ast.dump(node_obj, annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE()], [Str('bar'), Str('baz')]))])"
>>> ast.dump(ast.parse("'foo' < 'bar' <= 'baz' >= 'quux'"), annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE(), GtE()], [Str('bar'), Str('baz'), Str('quux')]))])"

현재 허용되는 답변과 달리 삼항 연산은 일반 비교 연산으로, 첫 번째 표현식, 특정 비교의 반복 가능 및 필요에 따라 평가할 수있는 표현 노드의 반복 가능을 취합니다. 단순한.

파이썬에 대한 결론

필자는 개인적으로 범위 의미가 매우 우아하다는 것을 알고 있으며, 내가 아는 대부분의 Python 전문가는 기능을 손상시키는 대신 고려하여 기능의 사용을 권장합니다.

코드는 작성된 것보다 훨씬 많이 읽습니다. Fear, Uncertainty 및 Doubt 의 일반 관중을 키우면 코드의 가독성을 향상시키는 변경 사항이 적용되지 않아야합니다 .

그렇다면 왜 프로그래밍 언어에서 x <y <z를 사용할 수 없습니까?

나는 기능의 상대적 중요성과 언어 총재가 허용하는 변화의 운동량 / 관성을 중심으로하는 이유의 합류가 있다고 생각합니다.

다른 중요한 언어 기능에 대해서도 비슷한 질문을 할 수 있습니다

Java 또는 C #에서 다중 상속을 사용할 수없는 이유는 무엇입니까? 여기서 어느 쪽의 질문에 대한 답은 없습니다 . Bob Martin이 주장한 것처럼 개발자가 너무 게으른 것일 수 있으며 주어진 이유는 단지 변명 일뿐입니다. 그리고 다중 상속은 컴퓨터 과학에서 매우 큰 주제입니다. 연산자 체인보다 확실히 중요합니다.

간단한 해결 방법이 있습니다

비교 연산자 체인은 우아하지만 다중 상속만큼 중요한 것은 아닙니다. Java와 C #에서 해결 방법으로 인터페이스를 사용하는 것처럼 여러 비교를위한 모든 언어도 마찬가지입니다. 비교를 부울 "and"로 연결하면 쉽게 작동합니다.

대부분의 언어는위원회가 관리합니다

대부분의 언어는 (파이썬과 같이 현명한 자비로운 독재자가 아닌)위원회에 의해 발전하고 있습니다. 그리고 저는이 문제가 각위원회에서이를 해결하기에 충분한지지를 얻지 못했다고 추측합니다.

이 기능을 제공하지 않는 언어가 변경 될 수 있습니까?

언어 x < y < z가 예상되는 수학적 의미론없이 허용된다면 , 이것은 중대한 변화 일 것입니다. 처음부터 허용하지 않으면 거의 추가하기가 쉽지 않습니다.

주요 변경 사항

주요 변경 사항이있는 언어와 관련하여 : Google은 주요 변경 사항이있는 언어를 업데이트하지만 사용자는 특히 좋아하지 않는 기능의 사용자를 좋아하지 않는 경향이 있습니다. 사용자가의 이전 행동에 의존하고 있다면 x < y < z크게 항의 할 것입니다. 그리고 대부분의 언어가위원회에 의해 지배되기 때문에 그러한 변화를지지 할 정치적 의지를 많이 얻지 못할 것입니다.


솔직히는 정신적지도에 대한 사소한 현상 체인 비교 예 'X <Y <Z'와 같은 동작을하지만 것을 언어가 제공하는 의미 어떠한 문제를 취하지 x < y < z(x < y) && (y < z). 연쇄 비교를위한 정신 모델 인 nits를 따는 것은 일반적인 수학입니다. 고전적인 비교는 일반적으로 수학이 아니라 부울 논리입니다. x < y이진 응답을 생성합니다 {0}. y < z이진 응답을 생성합니다 {1}. {0} && {1}설명적인 답변을 생성합니다. 논리는 순진하게 연결되지 않고 구성됩니다.
K. Alan Bates

더 나은 의사 소통을 위해 전체 내용을 직접 요약하는 한 문장으로 답을 시작했습니다. 긴 문장이므로 글 머리 기호로 나 bro습니다.
Aaron Hall

2
이 기능을 구현하는 언어가 거의없는 주요 이유는 Guido 이전에는 아무도 그것에 대해 생각하지 않았기 때문입니다. C에서 상속받은 언어는 주로 C 개발자가 40 년 전에 "잘못된"(수학적으로 잘못된) 언어를 사용했기 때문에이 "올바르게"(수학적으로 올바른) 언어를 얻을 수 없습니다. 언어가 해석하는 방식의 반 직관적 인 특성에 따라 많은 코드가 있습니다 x<y<z. 언어는 한 번 이런 권리를 얻을 기회가 있으며, 그 기회는 언어의 시작에 있습니다.
David Hammen

1
@ K.AlanBates 당신은 1) 연산자 체인이 조잡하고 2) 구문 설탕이 가치가 없다는 2 점을 만듭니다. 첫 번째로 : 운영자 체인이 100 % 결정적이라는 것을 입증했습니다. 아마도 일부 프로그래머는 구조를 이해하는 능력을 확장하기에 정신적으로 게으르다? 두 번째 요점 : 가독성을 직접적으로 주장하는 것처럼 들리나요? 구문 설탕은 일반적으로 가독성을 향상시킬 때 좋은 것으로 간주되지 않습니까? 이런 식으로 생각하는 것이 정상이라면 왜 프로그래머가 그렇게 의사 소통하고 싶지 않습니까? 코드는 읽을 수 있도록 작성해야합니다.
Aaron Hall

2
I have watched both Ruby and Python implement breaking changes.: 호기심이 사람들을 위해, 여기에 루프 변수와 폐쇄 포함하는 C # 5.0에서 깨는 변화의 blogs.msdn.microsoft.com/ericlippert/2009/11/12/...
user2023861을

13

컴퓨터 언어는 가능한 가장 작은 단위를 정의하고 조합 할 수 있도록합니다. 가능한 가장 작은 단위는 "x <y"와 같으며 부울 결과를 제공합니다.

삼항 연산자를 요청할 수 있습니다. 예는 x <y <z입니다. 이제 어떤 연산자 조합을 허용합니까? 분명히 x> y> z 또는 x> = y> = z 또는 x> y> = z 또는 x == y == z가 허용되어야합니다. x <y> z는 어떻습니까? x! = y! = z? 마지막 것은 x! = y 및 y! = z 또는 무엇을 의미합니까?

이제 인수 승격 : C 또는 C ++에서 인수는 공통 유형으로 승격됩니다. 그렇다면 x <y <z의 의미는 x의 두 배이지만 y와 z는 긴 정수입니다. 세 사람 모두 두 배로 승진 했습니까? 아니면 y는 두 배로, 다른 시간은 오래 걸리나요? C ++에서 연산자 중 하나 또는 둘 다에 과부하가 걸리면 어떻게됩니까?

마지막으로 피연산자 수를 허용합니까? <b> c <d> e <f> g처럼?

글쎄, 그것은 모두 매우 복잡해집니다. 이제 마음에 들지 않는 것은 구문 오류를 생성하는 x <y <z입니다. 그것의 유용성은 x <y <z가 실제로 무엇을하는지 알 수없는 초보자들에 대한 피해에 비해 작기 때문입니다.


4
간단히 말해, 디자인하기가 어려운 기능 일뿐입니다.
Jon Purdy

2
언어에이 기능이 포함 된 언어를 잘 모르는 이유를 설명 할 이유가 아닙니다. 사실, 잘 정의 된 방식으로 언어에 포함시키는 것은 매우 쉽습니다. 모든 연산자가 이진 연산자가 아닌 비슷한 유형의 연산자로 연결된 목록으로 보는 것이 문제입니다. x + y + z의미 론적 차이를 의미하지 않는 유일한 차이 로 sum에 대해서도 동일하게 수행 할 수 있습니다 . 잘 알려진 언어는 그렇게하지 않았습니다.
cmaster

1
파이썬에서이 최적화의 비트 (의 생각 x < y < z에 해당되는 ((x < y) and (y < z))지만을 가진 y유일한 평가 한 번 내가 컴파일 상상 언어 주위에 그들의 방법을 최적화 할 것). "x <y <z가 실제로 무엇을하는지 알 수없는 초보자들에게주는 피해에 비해 유용성이 적습니다." 나는 그것이 매우 유용하다고 생각합니다. 아마 그 일에 -1을 할 것입니다.
Aaron Hall

가장 어리석은 프로그래머와 혼동 될 수있는 모든 것을 제거하는 언어를 디자인하는 것이 목표라면 COBOL과 같은 언어가 이미 존재합니다. 나는 오히려 a < b > c < d > e < f > g"명백한"의미로 실제로 쓸 수있는 파이썬을 사용하고 싶다 (a < b) and (b > c) and (c < d) and (d > e) and (e < f) and (f > g). 글을 쓸 수 있다고해서 꼭 그래야하는 것은 아닙니다. 이러한 괴로움을 없애는 것은 코드 검토의 범위입니다. 반면 0 < x < 8에 파이썬으로 글을 쓰는 것은 x가 0에서 8 사이에 있다는 것을 의미하는 명백한 따옴표가 없습니다.
David Hammen

아이러니하게도 @DavidHammen, COBOL은 실제로 a <b <c
JoelFan

10

많은 프로그래밍 언어에서 x < y두 개의 피연산자를 허용 하고 단일 부울 결과로 평가 되는 이진 식입니다 . 따라서, 복수의 표현을 체인, 경우 true < zfalse < z의미를, 그 표현이 성공적으로 평가되는 경우, 그들은 가능성이 잘못된 결과를 얻을 수있는 좋은 방법입니다하지 않습니다.

두 개의 매개 변수를 사용하고 단일 부울 결과를 생성하는 함수 호출x < y 로 생각하는 것이 훨씬 쉽습니다 . 실제로, 그것은 많은 언어가 그것을 구현하는 언어입니다. 컴포지션 가능하고 쉽게 컴파일 가능하며 작동합니다.

x < y < z시나리오는 훨씬 더 복잡하다. 이제 컴파일러는, 효과, 패션이 세 가지 기능 : x < y, y < z, 그 두 값의 결과는 전혀 틀림의 컨텍스트 내에서, AND로 모호한 언어 문법 .

왜 다른 방법으로 했습니까? 모호하지 않은 문법이기 때문에 구현하기가 훨씬 쉽고 정확하기가 훨씬 쉽습니다.


2
언어를 디자인하는 경우 올바른 결과를 얻을 수있는 기회가 있습니다.
JesseTG

2
물론 그것은 질문에 대답합니다. 질문이 정말 이유 라면 "언어 디자이너가 선택한 것이기 때문"입니다. 그것보다 더 나은 대답을 얻을 수 있다면 그것을 찾으십시오. Gnasher는 본질적으로 그의 대답 의 첫 번째 단락에서 똑같은 내용을 언급 했습니다 .
Robert Harvey

3
다시, 당신은 머리카락을 나누고 있습니다. 프로그래머는 그렇게하는 경향이 있습니다. "쓰레기를 꺼내시겠습니까?" "아니." "쓰레기를 꺼낼 래?" "예."
Robert Harvey

2
나는 또한 마지막 단락에 이의를 제기합니다. 파이썬은 체인 비교를 지원하며 파서는 LL (1)입니다. 의미를 정의하고 구현하는 것이 반드시 어려운 것은 아닙니다 . Python 은 각 표현식이 한 번만 평가된다는 점 e1 op1 e2 op2 e3 op3 ...e1 op e2 and e2 op2 e3 and ...제외하고 는 동일 하다고 말합니다 . (BTW이 간단한 규칙에는 a == b is True더 이상 의도 한 효과가없는 혼동되는 부작용 이 있습니다.)

2
@RobertHarvey re:answer이것은 주요 질문에 대한 나의 의견을 위해 즉시 마음이가는 곳이었습니다. x < y < z언어 의미에 특정 값을 추가하는 것에 대한 지원은 고려하지 않습니다 . (x < y) && (y < z)보다 광범위하게 지원되고,보다 명확하고, 표현 적이며, 구성 요소로보다 쉽게 ​​소화되고, 구성 가능하고, 논리적이고,보다 쉽게 ​​리팩토링됩니다.
K. Alan Bates

6

대부분의 주류 언어는 (적어도 부분적으로) 객체 지향적입니다. 기본적으로 OO의 기본 원칙은 객체가 다른 객체 (또는 자신)에게 메시지를 보내고 해당 메시지 의 수신자 가 해당 메시지에 응답하는 방법을 완전히 제어한다는 것입니다.

자, 우리가 어떻게 구현할 것인지 봅시다

a < b < c

왼쪽에서 오른쪽으로 엄격하게 평가할 수 있습니다 (왼쪽 연관).

a.__lt__(b).__lt__(c)

그러나 이제 우리 __lt__는의 결과를 요구 a.__lt__(b)합니다 Boolean. 말이되지 않습니다.

올바른 연관성을 시도해 봅시다.

a.__lt__(b.__lt__(c))

아니, 그건 말도 안돼 이제, 우리는 a < (something that's a Boolean).

좋아, 그것을 설탕으로 취급하는 것은 어떻습니까? 일련의 n 개의 <비교가 n-1-ary 메시지를 보내도록 합시다 . 이것은 우리에게 메시지 __lt__a전달 b하고 c인수로 전달 한다는 것을 의미 할 수 있습니다 .

a.__lt__(b, c)

좋아, 작품,하지만 이상한 비대칭은 여기있다 : a그것보다 작은 지 여부를 결정 얻는다 b. 그러나 b그것보다 작은 지 여부를 결정하지 않는 c결정이되는 대신에 있음을, 또한 에 의해 만들어진 a.

n-ary 메시지 보내기로 해석하는 것은 this어떻습니까?

this.__lt__(a, b, c)

마침내! 이것은 효과가 있습니다. 그러나 객체의 순서는 더 이상 객체 의 속성이 아니고 (예를 들어 속성의 속성 a보다 적거나 b같지 않은 ) 컨텍스트 의 속성 (즉, )입니다.abthis

주류 관점에서 보면 이상해 보입니다. 그러나 Haskell에서는 정상입니다. Ord예를 들어 typeclass에는 여러 가지 다른 구현이있을 수 있으며 , a보다 작은 지 여부 는 btypeclass 인스턴스가 범위에 속 하는지 여부 에 따라 다릅니다.

그러나 실제로는 그렇지 않아 전혀 이상한! Java ( Comparator) 및 .NET ( IComparer)에는 정렬 알고리즘에 자신의 순서 관계를 주입 할 수있는 인터페이스가 있습니다. 따라서 그들은 순서가 유형에 고정되는 것이 아니라 컨텍스트에 의존한다는 것을 완전히 인정합니다.

내가 아는 한, 현재 그러한 번역을 수행하는 언어는 없습니다. 그러나 우선 순위가 있습니다. IokeSeph 는 디자이너가 " 삼항 연산자"라고 부르는 것 – 구문 적으로 이진이지만 의미 적으로 삼항 인 연산자를가 집니다. 특히,

a = b

되어 있지 메시지를 보내는 것으로 해석 =a전달 b인자로, 오히려 같은 메시지를 보내 ="현재 접지"(유사하지만 동일하지는 개념에 this) 전달 ab인수로. 따라서 다음과 a = b같이 해석됩니다

=(a, b)

그리고 아닙니다

a =(b)

이것은 n-ary 연산자로 쉽게 일반화 될 수 있습니다.

이것은 실제로 OO 언어에 고유합니다. 오픈 오피스에는 항상 메시지 전송을 해석 할 책임이있는 하나의 단일 객체가 있으며, 우리가 본 것처럼 a < b < c어떤 객체가되어야하는지에 대해서는 즉시 명확하지 않습니다 .

그러나 절차 적 또는 기능적 언어에는 적용되지 않습니다. 예를 들어, Scheme , Common LispClojure 에서 <함수는 n-ary이며 임의의 수의 인수로 호출 할 수 있습니다.

특히, <수행 하지 의미는 "이하", 오히려 이러한 기능은 약간 다르게 해석됩니다 :

(<  a b c d) ; the sequence a, b, c, d is monotonically increasing
(>  a b c d) ; the sequence a, b, c, d is monotonically decreasing
(<= a b c d) ; the sequence a, b, c, d is monotonically non-decreasing
(>= a b c d) ; the sequence a, b, c, d is monotonically non-increasing

3

언어 디자이너가 생각하지 않았거나 좋은 생각이라고 생각하지 않았기 때문입니다. 파이썬은 간단한 (거의) LL (1) 문법으로 설명 된대로 수행합니다.


1
이것은 여전히 ​​거의 모든 주류 언어에서 일반적인 문법으로 구문 분석됩니다. @RobertHarvey가 준 이유 때문에 그것은 정확하게 이해되지 않을 것입니다.
메이슨 휠러

@MasonWheeler 아니요, 반드시 그런 것은 아닙니다. 비교가 다른 연산자와 상호 교환 가능하도록 (예 : 우선 순위가 동일하기 때문에) 규칙을 작성하면 올바른 동작을 얻지 못합니다. 파이썬이 모든 비교를 한 수준으로 진행한다는 사실은 시퀀스를 결합으로 취급 할 수있게 해줍니다.
Neil G

1
실제로는 아닙니다. 1 < 2 < 3Java 또는 C #에 넣으면 연산자 우선 순위에 문제가 없습니다. 잘못된 유형에 문제가 있습니다. 문제는 이것이 작성한 그대로 정확하게 구문 분석되지만 컴파일러에서 개별 비교 시퀀스를 체인 비교로 바꾸려면 특수 사례 논리가 필요하다는 것입니다.
메이슨 휠러

2
@MasonWheeler 제가 말하는 것은 작동하도록 언어를 설계해야한다는 것입니다. 그 중 한 부분은 문법을 올바르게하는 것입니다. (같은 우선 순위를 가지고 있기 때문에 다른 연산자와 비교할 수 있도록 규칙을 작성하면 올바른 동작을 얻지 못합니다.) AST를 CAST로 해석하는 것은 C ++입니다. 하지 않습니다. 내 대답의 주요 요점은 언어 디자이너의 결정이라는 것입니다.
Neil G

@MasonWheeler 동의합니다. 나는 이것에 문법을 맞추기가 어렵지 않다는 것을 강조했다. 이런 식으로 작동하기를 미리 결정하는 것입니다.
Neil G

2

다음 C ++ 프로그램은 가능한 가장 높은 수준 ( -Weverything) 으로 경고를 설정 한 경우에도 clang의 neep peep으로 컴파일합니다 .

#include <iostream>
int main () { std::cout << (1 < 3 < 2) << '\n'; }

반면에 gnu 컴파일러 스위트는 저에게 그 사실을 잘 알려줍니다 comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses].

그래서 내 질문은 이것입니다 : 왜 예상되는 의미론을 가지고 x <y <z가 프로그래밍 언어에서 일반적으로 사용 가능하지 않습니까?

대답은 간단합니다 : 이전 버전과의 호환성. 야생에 상당량의 코드가 있으며 그와 동등한 것을 사용 1<3<2하고 결과가 사실이라고 기대합니다.

언어 디자이너는이 "올바른"기능을 얻을 수있는 기회가 한 번 밖에 없으며, 이것이 언어가 처음 설계된 시점입니다. 처음에 "잘못"하게되면 다른 프로그래머들이 그 "잘못된"행동을 빨리 이용하게됩니다. 두 번째로 "올바르게"얻으면 기존 코드 기반이 손상됩니다.


이 프로그램은 수학에서 명백히 거짓 인 표현의 결과로 '1'을 출력하기 때문에 +1입니다. 이 언어 기능이 추가되면 이해하기 어려운 변수 이름을 가진 실제 예제는 디버깅 악몽이 될 것입니다.
Seth Battin

@SethBattin-이것은 파이썬의 악몽이 아닙니다. 파이썬의 유일한 문제는 if x == y is True : ...나의 의견입니다. 그런 종류의 코드를 작성하는 사람들은 (지금 그가 살아 있다면) Torquemada 자신을 희미하게 만들 특별한 특별하고 특별한 종류의 고문을 당할 가치가 있습니다.
David Hammen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.