단락 평가

Short-circuit evaluation

단락 평가, 최소 평가 또는 McCarthy 평가(John McCarthy 이후)는 일부 프로그래밍 언어에서 두 번째 인수가 식 값을 결정하는 데 충분하지 않은 경우에만 실행되거나 평가되는 일부 부울 연산자의 의미입니다.AND함수는 로 평가된다false전체 값은 다음과 같아야 합니다.false의 첫 번째 인수가OR함수는 로 평가된다true전체 값은 다음과 같아야 합니다.true.

느린 평가를 사용하는 프로그래밍 언어(Lisp, Perl, Haskell)에서는 일반적인 부울 연산자는 단락입니다.기타(Ada, Java, Delphi)에서는 단락 연산자와 표준 부울 연산자를 모두 사용할 수 있습니다.배타적 또는 (XOR)과 같은 일부 부울 연산에서는 양쪽 오퍼랜드가 항상 결과를 판별하기 위해 필요하기 때문에 단락할 수 없습니다.

단락 연산자는 엄격하지 않기 때문에 사실상 단순한 산술 연산자가 아닌 제어 구조이다.부작용이 중요한 명령어 용어(특히 C와 C++)에서 단락 연산자는 시퀀스 포인트를 도입하여 (선택적으로) 두 번째 인수를 처리하기 전에 부작용을 포함한 첫 번째 인수를 완전히 평가한다.ALGOL 68은 사용자 정의 단락 연산자와 절차를 달성하기 위해 절차를 사용했습니다.

단락 연산자의 사용은 문제가 있다고 지적되어 왔습니다.

조건부 접속(줄여서 cand와 cor)은 다음과 같습니다.첫눈에 보이는 것보다 덜 순진해요예를 들어 cor는 cand에 분산되지 않습니다: compare

(A cand B) cor C with (A cor C) cand (B cor C)

'A' C'의 경우 두 번째 표현은 B를 정의할 필요가 있지만 첫 번째 표현은 정의할 필요가 없습니다.따라서 조건부 연결은 프로그램에 대한 공식적인 추론을 복잡하게 만들기 때문에 피하는 것이 좋습니다.

--

정의.

단락 평가를 구현하는 프로그래밍 언어에서 표현식은x and y조건식과 같다 if x then y else x, 및 식x or y와 동등하다if x then x else y어느 경우든 x는 한 번만 평가됩니다.

위의 일반화된 정의는 두 가지 이상의 진실 값을 가진 느슨하게 입력된 언어를 수용합니다. True그리고.False여기서 단락 연산자는 마지막으로 평가한 서브 표현을 반환할 수 있습니다.아래 표에서는 이것을 "마지막 값"이라고 부릅니다.엄밀하게 타이핑된 언어의 경우 이 표현은 다음과 같이 간략화됩니다.if x then y else false그리고.if x then true else y각각 부울 케이스에 대해.

우선 순위

비록 ~일지라도AND보다 우선하다OR많은 언어에서 이것은 단락 평가의 보편적 속성이 아니다.2개의 연산자가 같은 우선순위를 가지며 서로 왼쪽 어소시에이트 되어 있는 예로는 POSIX 셸의 명령어목록 [2]: §2.9.3 구문이 있습니다.

다음의 간단한 왼쪽에서 오른쪽 평가자는 우선 순위를 적용합니다.AND에 걸쳐서OR에 의해continue:

함수 short-circuit-eval(오류, ): (오류, )의 각 (op, val)에 대해 True: op = "AND" & & result = false continue = "OR" & result = True return result: = val returning result:

형식화

부작용이 있든 없든 단락 논리는 Hoare의 조건을 기반으로 공식화되었습니다.그 결과, 단락 로직에서 비단락 연산자를 정의하여 동일한 [3]평가 시퀀스를 가질 수 있습니다.

공통 프로그래밍 및 스크립트 언어 지원

다양한 언어의 부울 연산자
언어 열심인 연산자 단락 연산자 결과 유형
고급 비즈니스 애플리케이션 프로그래밍(ABAP) 없음. and,or 부울1
아다 and,or and then,or else 부울
알골 68 및 &, ;; 또는 ∨ andf , orf (둘사용자 정의) 부울
APL ,,(표준),(또한) 등 :AndIf,:OrIf 부울1
아악 없음. &&, 부울
배쉬 없음. &&, 부울
C, Objective-C 없음. &&, ,?[4] int (&&, opnd 의존 (?)
C++2 없음. &&, ,?[5] 부울(&&, opnd 의존 (?)
C# &, &&, ,?,?? 부울(&&, opnd 의존 (?,??)
ColdFusion Markup Language(CFML) 없음. AND,OR,&&, 부울
D3 &, &&, ,? 부울(&&, opnd 의존 (?)
에펠 and,or and then,or else 부울
얼랑 and,or andalso,orelse 부울
포트란4 .and.,.or. .and.,.or. 부울
Go, Haskell, OCaml 없음. &&, 부울
Java, MATLAB, R, Swift &, &&, 부울
자바스크립트, 줄리아 &, &&, 마지막 값
라소 없음. and,or,&&, 마지막 값
코틀린 and,or &&, 부울
리스프, 루아, 스킴 없음. and,or 마지막 값
유행성 이하선염(M) &,! 없음. 숫자
모듈라-2 없음. AND,OR 부울
오베론 없음. &,OR 부울
OCaml 없음. &&, 부울
파스칼 and,or5,9 and_then,or_else6,9 부울
&, &&,and, ,or 마지막 값
루비 and,or &&, 마지막 값
PHP &, &&,and, ,or 부울
POSIX 쉘(명령어 리스트) 없음. &&, 마지막 값(종료)
파이썬 &, and,or 마지막 값
&, &&, [6] 부울
스몰토크 &, and:,or:7 부울
표준 ML 불명 andalso,orelse 부울
TTCN-3 없음. and,or[7] 부울
Beckhof TwinCAT® (IEC 61131-3)10 AND,OR AND_THEN,[8] OR_ELSE[9] 부울
Visual Basic.그물 And,Or AndAlso,OrElse 부울
Visual Basic, VBA(Visual Basic for Applications) And,Or Select Case8 숫자
울프람어 And @@ {...},Or @@ {...} And,Or,&&, 부울
ZTT &, 없음. 부울

1 ABAP 및 APL에는 고유한 부울 타입이 없습니다.
2 과부하 시 연산자는&&그리고. 모든 유형을 반환할 수 있습니다.
3 이는 런타임 평가식에만 적용됩니다.static if그리고.static assert. 정적 이니셜라이저 또는 매니페스트 상수의 표현식은 열띤 평가를 사용합니다.
4 Fortran 연산자는 단락되지도 않고 열심도 없습니다.언어 사양을 통해 컴파일러는 최적화 방법을 선택할 수 있습니다.
5ISO/IEC 10206:1990 Extended Pascal은 단락을 허용하지만 필수는 아닙니다.
6 ISO/IEC 10206:1990 확장 Pascal 지원and_then그리고.or_else를 클릭합니다.[10]
7 Smalltalk는 다음과 같은 인수가 있는 한 단락 의미론을 사용합니다.and:블록(예:false and: [Transcript show: 'Wont see me']).
CASE 스테이트먼트를 지원하는 BASIC 언어에서는 고정 라벨로 제한된 점프 테이블이 아닌 조건부 평가 시스템을 사용하여 이 작업을 8수행했습니다.
9DelphiFree Pascal은 기본적으로 단락 평가입니다.이는 컴파일러 옵션에 따라 변경될 수 있지만 널리 사용되는 것 같지는 않습니다.
10 표준 IEC 61131-3은 실제로 다음과 같은 사항을 정의하지 않는다.AND그리고.OR단락 평가를 사용하여 연산자를 정의하지 않습니다.AND_THEN그리고.OR_ELSE. 표의 항목은 Beckhoff TwinCAT®에서 작동하는 방식을 보여줍니다.

일반적인 용도

두 번째 인수의 바람직하지 않은 부작용 회피

C 기반 언어를 사용하는 일반적인 예:

인트 분파 = 0; 한다면 (분파 != 0 & & 숫자 / 분파) {     ... // num/calculation을 통해 0으로 나누기 오류가 발생하지 않도록 합니다. } 

다음 예를 생각해 보겠습니다.

인트 a = 0; 한다면 (a != 0 & & 마이펑크(b)) {     무엇인가 하다(); } 

이 예에서는 단락 평가를 통해 다음 사항이 보증됩니다.myfunc(b)는 호출되지 않습니다.그 이유는a != 0false로 평가됩니다.이 기능을 통해 두 가지 유용한 프로그래밍 구성을 사용할 수 있습니다.

  1. 첫 번째 하위식이 비싼 계산이 필요한지 여부를 확인하고 검사가 거짓으로 평가되면 두 번째 인수에서 비싼 계산을 제거할 수 있습니다.
  2. 첫 번째 식이 없으면 런타임 오류가 발생할 수 있는 조건을 보증하는 구성을 허용합니다.

둘 다 다음 C 스니펫에 설명되어 있습니다.여기에서는 최소한의 평가로 늘포인터 참조 해제와 메모리 초과 페치가 모두 방지됩니다.

부울 is_first_char_valid_alpha_module(컨스턴트  *p) {     돌아가다 알파(p[0]); // p == NULL일 경우 SEGFAULT 가능성이 높음 }  부울 is_first_char_valid_alpha(컨스턴트  *p) {     돌아가다 p != 특수한 순서 & & 알파(p[0]); // 1) p == NULL인 불필요한 isalpha() 실행 없음, 2) SEGFAULT 위험 없음 } 

관용 조건 구문

최소 평가는 연산자의 의미 정의의 일부이며 선택적인 최적화가 아니기 때문에, 많은 코딩 관용구는 간결한 조건부 구성으로서 그것에 의존한다.예를 들어 다음과 같습니다.

Perl 숙어:

어떤 조건 또는 죽어버려;    # some_condition이 false일 경우 실행을 중단합니다. 어떤 조건 그리고. 죽어버려;   # some_condition이 true이면 실행을 중단합니다. 

POSIX 쉘 숙어:[11]

modprobe -q some_some_sometry & echo "some_sometry installed" 에코 "some_sometry not inst

이 고사성어는 을 전제로 하고 있다echo실패할 리가 없습니다.

생각할 수 있는 문제

테스트되지 않은 두 번째 상태는 수행되지 않은 부작용으로 이어집니다.

이러한 이점에도 불구하고 최소한의 평가로 인해 발생 사실을 깨닫지 못하는(또는 잊어버리는) 프로그래머에게 문제가 발생할 수 있습니다.예를 들어, 코드에서는

한다면 (표현a & & 마이펑크(b)) {     무엇인가 하다(); } 

한다면myfunc(b)필요한 조작을 실행하도록 되어 있습니다.do_something()시스템 리소스 할당 등 실행되며,expressionA그러면 false로 평가됩니다.myfunc(b)가 실행되지 않아 문제가 발생할 수 있습니다.Java와 같은 일부 프로그래밍 언어에는 이 문제를 피하기 위해 최소 평가를 사용하는 연산자와 사용하지 않는 연산자가 있습니다.

수행되지 않은 부작용 문장의 문제는 적절한 프로그래밍 스타일로 쉽게 해결할 수 있다. 즉, 부울 문장에 부작용을 사용하지 않는 것이다. 평가에서 부작용 값을 사용하면 일반적으로 코드가 불투명해지고 오류가 발생하기 [12]쉽기 때문이다.

최적화를 억제하여 효율성 저하

단락으로 인해 최신 중앙 처리 장치(CPU)에서 분기 예측 오류가 발생하여 성능이 크게 저하될 수 있습니다.주목할 만한 예는 광선 [clarification needed]추적에서 축 정렬 상자 교차 코드를 사용하여 고도로 최적화된 광선입니다.일부 컴파일러는 이러한 경우를 탐지하여 더 빠른 코드를 내보낼 수 있지만 프로그래밍 언어 의미론은 이러한 [citation needed]최적화를 제한할 수 있습니다.

컴파일러가 이러한 경우에 최적화할 수 없는 예로는 2012년 [13]현재 Java의 핫스팟 VM이 있습니다.

「 」를 참조해 주세요.

레퍼런스

  1. ^ Edsger W. Dijkstra "다소 실망스러운 서신에 대하여", EWD1009-0, 1987년 5월 25일 전문
  2. ^ "Shell Command Language". pubs.opengroup.org.
  3. ^ Jan A. Bergstra, A. Ponse, D.J.C. Staudt (2010). "Short-circuit logic". arXiv:1010.3674 [cs.LO].{{cite arxiv}}: CS1 maint: 작성자 파라미터 사용(링크)
  4. ^ ISO/IEC 9899 표준, 섹션 6.5.13
  5. ^ ISO/IEC는 14882 드래프트입니다.
  6. ^ "std::ops - Rust". doc.rust-lang.org. Retrieved 2019-02-12.
  7. ^ ETSI ES 201 873-1 V4.10.1, 섹션 7.1.4
  8. ^ "Beckhoff Information System - English". infosys.beckhoff.com. Retrieved 2021-08-16.
  9. ^ "Beckhoff Information System - English". infosys.beckhoff.com. Retrieved 2021-08-16.
  10. ^ "and_then - The GNU Pascal Manual". Gnu-pascal.de. Retrieved 2013-08-24.
  11. ^ "What does mean in bash?". stackexchange.com. Retrieved 2019-01-09.
  12. ^ "Referential Transparency, Definiteness and Unfoldability" (PDF). Itu.dk. Retrieved 2013-08-24.
  13. ^ Wasserman, Louis. "java - What are the cases in which it is better to use unconditional AND (& instead of &&)". Stack Overflow.