단락 평가
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 ,or 5,9 | and_then ,or_else 6,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 Case 8 | 숫자 |
울프람어 | 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수행했습니다.
9Delphi 및 Free 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 != 0
false로 평가됩니다.이 기능을 통해 두 가지 유용한 프로그래밍 구성을 사용할 수 있습니다.
- 첫 번째 하위식이 비싼 계산이 필요한지 여부를 확인하고 검사가 거짓으로 평가되면 두 번째 인수에서 비싼 계산을 제거할 수 있습니다.
- 첫 번째 식이 없으면 런타임 오류가 발생할 수 있는 조건을 보증하는 구성을 허용합니다.
둘 다 다음 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이면 실행을 중단합니다.
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이 있습니다.
「 」를 참조해 주세요.
레퍼런스
- ^ Edsger W. Dijkstra "다소 실망스러운 서신에 대하여", EWD1009-0, 1987년 5월 25일 전문
- ^ "Shell Command Language". pubs.opengroup.org.
- ^ Jan A. Bergstra, A. Ponse, D.J.C. Staudt (2010). "Short-circuit logic". arXiv:1010.3674 [cs.LO].
{{cite arxiv}}
: CS1 maint: 작성자 파라미터 사용(링크) - ^ ISO/IEC 9899 표준, 섹션 6.5.13
- ^ ISO/IEC는 14882 드래프트입니다.
- ^ "std::ops - Rust". doc.rust-lang.org. Retrieved 2019-02-12.
- ^ ETSI ES 201 873-1 V4.10.1, 섹션 7.1.4
- ^ "Beckhoff Information System - English". infosys.beckhoff.com. Retrieved 2021-08-16.
- ^ "Beckhoff Information System - English". infosys.beckhoff.com. Retrieved 2021-08-16.
- ^ "and_then - The GNU Pascal Manual". Gnu-pascal.de. Retrieved 2013-08-24.
- ^ "What does mean in bash?". stackexchange.com. Retrieved 2019-01-09.
- ^ "Referential Transparency, Definiteness and Unfoldability" (PDF). Itu.dk. Retrieved 2013-08-24.
- ^ Wasserman, Louis. "java - What are the cases in which it is better to use unconditional AND (& instead of &&)". Stack Overflow.