문제

언어가 사용되지 않는 이유 단락 평가? 사용하지 않으면 이점이 있습니까?

공연 문제로 이어질 수 있다는 것을 알았습니다 ... 사실입니까? 왜요?


관련 질문 : 단락 평가 사용의 이점

도움이 되었습니까?

해결책

단락 평가를 사용하지 않는 이유 :

  1. 기능이 다르게 행동하고 다른 결과를 생성하기 때문에 속성을 가져 오거나 운영자 방법에 부작용이 있습니다. 그리고 이것은 다음과 상충 될 수 있습니다. a) 언어 표준, b) 언어의 이전 버전 또는 c) 언어 일반 사용자의 기본 가정. 이것이 VB가 단락되지 않은 이유입니다.

  2. 컴파일러가 사용자가 입력 한 순서 대신 적합한 표현식, 운영자 및 하위 표현을 자유롭게 지정할 수 있기를 원할 수도 있습니다. SQL이 짧은 회로를 사용하지 않는 이유입니다. (또는 적어도 대부분의 개발자가 SQL에 오는 방식이 아닙니다). 따라서 SQL (및 일부 언어) 5월 단락이지만, 암시 적으로 지정된 순서대로 결정적이고 반드시 필요한 경우에만.

여기서는 "자동, 암시 적 순서-특이 적 단락"에 대해 묻고 있다고 가정합니다. 이는 대부분의 개발자가 C, C ++, C#, Java 등에서 기대하는 것입니다. VB와 SQL은 모두 명시 적으로 방법을 가지고 있습니다. 주문 별 단락. 그러나 일반적으로 사람들 이이 질문을 할 때 "내가 의미하는 바"질문입니다. 즉, 그들은 "내가 원하는 것을 왜하지 않습니까?"를 의미합니다.

다른 팁

내가 생각할 수있는 한 가지 이점은 일부 운영에 당신이 기대할 수있는 부작용이있을 수 있다는 것입니다.

예시:

if (true || someBooleanFunctionWithSideEffect()) {
    ...
}

그러나 그것은 일반적으로 눈살을 찌푸립니다.

ADA는 기본적으로 수행하지 않습니다. 단락 평가를 강제하려면 사용해야합니다. and then 또는 or else 대신에 and 또는 or.

문제는 실제로 물건을 느리게하는 상황이 있다는 것입니다. 두 번째 조건이 빠르게 계산되고 첫 번째 조건이 거의 항상 "또는"또는 "또는"또는 "또는 거짓"이라면 추가 체크 브랜치 명령은 일종의 폐기물입니다. 그러나 지점 예측 변수가있는 현대 프로세서에서는 그렇지 않습니다. 또 다른 문제는 컴파일러가 절반은 저렴하거나 실패 할 가능성이 높으며 그에 따라 수표를 재정렬 할 수 있습니다 (단락 동작이 정의 된 경우에는 할 수 없습니다).

두 번째 테스트에 부작용이있는 경우 코드의 예기치 않은 동작으로 이어질 수 있다는 반대 의견을 들었습니다. IMHO 당신이 당신의 언어를 잘 모른다면 그것은 단지 "예상치 못한"일 뿐이지 만, 일부는 이것을 주장 할 것입니다.

이 문제에 대해 실제 언어 설계자가 무엇을 말해야하는지에 관심이있는 경우 여기에서 발췌 한 내용이 있습니다. ADA 83 (원래 언어) 이론적 근거:

A 및 B와 같은 부울 표현의 피연산자는 어떤 순서로도 평가 될 수 있습니다. 용어 B의 복잡성에 따라 A 항에 값이 참을 때만 B를 평가하는 것이 더 효율적일 수 있습니다 (일부 기계에서는 아님). 그러나 이것은 컴파일러가 취한 최적화 결정 이며이 최적화가 항상 이루어 졌다고 가정하는 것은 부정확합니다. 다른 상황에서는 이전 조건이 만족되는 경우에만 각 조건을 평가 해야하는 조건의 결합을 표현할 수 있습니다. 이 두 가지 작업은 단락 제어 양식으로 수행 될 수 있습니다 ...

Algol 60에서 완전한 평가가 달리 수행되기 때문에 조건부 표현을 사용 하여만 단락 평가의 효과를 달성 할 수 있습니다. 이것은 종종 지루한 구조물로 이어집니다 ...

몇몇 언어는 부울 조건을 평가하는 방법을 정의하지 않습니다. 결과적으로 단락 평가를 기반으로 한 프로그램은 휴대 할 수 없습니다. 이것은 부울 연산자를 단락 제어 양식에서 분리 할 필요성을 명확하게 보여줍니다.

내 예를보십시오 SQL Server에서 부울 운영자 단락 부울 단락이있는 경우 SQL의 특정 액세스 경로가 더 효율적인 이유를 보여줍니다. ~ 아니다 사용된. 내 블로그 예제는 SQL에서 단락을 가정하면 부울 단락에 실제로 의존하는 방법을 보여줍니다. SQL이 오른쪽을 먼저 평가하는 것입니다. 올바른 것으로 보이며 이로 인해 액세스 경로가 훨씬 향상되었습니다.

Bill은 단락을 사용하지 않고 더 자세히 철자하는 유효한 이유를 암시했습니다. 매우 평행 한 아키텍처는 때때로 분기 제어 경로에 문제가 있습니다.

예를 들어 Nvidia의 Cuda 아키텍처를 가져 가십시오. 그래픽 칩은 SIMT 아키텍처를 사용하므로 많은 병렬 스레드에서 동일한 코드가 실행됩니다. 그러나 이것 모든 스레드가 매번 동일한 조건부 분기를 사용하는 경우 작동합니다. 다른 스레드가 다른 코드 경로를 사용하는 경우 평가는 직렬화됩니다. 이는 일부 스레드가 필요하기 때문에 병렬화의 이점이 손실됨을 의미합니다. 기다리다 다른 사람들은 대체 코드 브랜치를 실행합니다.

짧은 회로는 실제로 코드를 분기하는 것과 관련이 있으므로 단락 작업은 CUDA와 같은 SIMT 아키텍처에서 유해 할 수 있습니다.

- 그러나 Bill이 말했듯이, 그것은 하드웨어 고려 사항입니다. 한 언어 가자, 나는 당신의 질문에 울부 짖음으로 대답 할 것입니다 아니요: 단락을 방지합니다 ~ 아니다 이해가됩니다.

나는 100 중 99 번 말하며 성능을 위해 단락 연산자를 선호한다고 말하고 싶습니다.

그러나 내가 사용하지 않을 곳을 찾은 두 가지 큰 이유가 있습니다. (그건 그렇고, 내 예제는 C에 있습니다. &&와 ||는 단락이 있고 & |

1.) 첫 번째 값에 관계없이 IF 문에서 두 개 이상의 함수를 호출하려는 경우.

if (isABC() || isXYZ()) // short-circuiting logical operator
    //do stuff;

이 경우 isxyz ()가 isabc ()가 false를 반환하는 경우에만 호출됩니다. 그러나 당신은 isxyz ()가 무엇이든 상관없이 호출되기를 원할 수 있습니다.

대신 당신은 이것을합니다 :

if (isABC() | isXYZ()) // non-short-circuiting bitwise operator
    //do stuff;

2.) 정수로 부울 수학을 수행 할 때.

myNumber = i && 8; // short-circuiting logical operator

반드시 같은 것은 아닙니다.

myNumber = i & 8; // non-short-circuiting bitwise operator

이 상황에서는 단락 연산자가 반드시 전체 표현식을 평가하지 않기 때문에 실제로 다른 결과를 얻을 수 있습니다. 그리고 그것은 부울 수학에서 기본적으로 쓸모가 없습니다. 따라서이 경우 비 쇼트 커뮤니케이션 (비트) 연산자를 대신 사용합니다.

내가 암시하는 것처럼,이 두 시나리오는 실제로 드물다. 그러나 두 유형의 운영자에게는 실제 프로그래밍 이유가 있음을 알 수 있습니다. 운 좋게도 오늘날 대부분의 인기있는 언어에는 두 가지가 있습니다. VB.NET조차도 안달 소 및 오렌스 단락 연산자가 있습니다. 오늘날 언어가 두 가지가 없다면 나는 그것이 시간 뒤에 있다고 말하고 실제로 프로그래머를 제한한다고 말합니다.

오른쪽을 평가하기를 원한다면 다음과 같습니다.

if( x < 13 | ++y > 10 )
    printf("do something\n");

아마도 당신은 Y가 X <13인지 여부에 관계없이 y를 섭취하기를 원했을 것입니다. 그러나이 작업에 대한 좋은 주장은 부작용없이 조건을 만드는 것이 일반적으로 프로그래밍 연습이 더 좋습니다.

스트레칭으로 :

언어가 매우 안전하기를 원한다면 (굉장한 비용으로) 단락 평가를 제거합니다. '안전한'무언가가 가변적 인 시간이 걸리면 타이밍 공격 그것을 엉망으로 만드는 데 사용될 수 있습니다. 단락 평가는 실행하는 데 다른 시간이 걸리므로 공격을위한 구멍을 뚫습니다. 이 경우 단락 평가를 허용하지 않으면보다 안전한 알고리즘 (WRT 타이밍 공격)을 작성하는 데 도움이 될 것입니다.

그만큼 아다 프로그래밍 언어는 회로가 단락하지 않은 부울 연산자를 지원했습니다.AND, OR), 컴파일러가 구조물을 최적화하고 병렬화 할 수 있도록, 단락에 대한 명시적인 요청으로 연산자AND THEN, OR ELSE) 그것이 프로그래머가 원하는 것일 때. 이러한 이중 가려진 접근 방식의 단점은 언어를 좀 더 복잡하게 만드는 것입니다 (1000 개의 디자인 결정과 같은 "두 가지 모두!"정맥은 프로그래밍 언어를 전체적으로 훨씬 더 복잡하게 만들 것입니다 ;-).

이것이 지금 어떤 언어로든 일어나고있는 일이라고 생각하는 것은 아니지만 작업의 양쪽을 다른 스레드에 공급하는 것은 다소 흥미로울 것입니다. 대부분의 피연산자는 서로를 방해하지 않기 위해 미리 결정될 수 있으므로 다른 CPU에 나눠주는 좋은 후보자가 될 수 있습니다.

이 사물은 여러 가지를 평가하고 하나를 선택하는 경향이있는 매우 평행 한 CPU에서 중요합니다.

이봐, 그것은 약간의 스트레칭이지만, 당신은 "왜 언어가 아닌가?"라고 물었다.

언어 광택 단락 평가를 사용하지 않습니다. IF-then-Elses에서, 두 가지와 다른 지점은 각 진드기에서 평가되며, 하나는 조건의 평가에 따라 조건부의 결과로 간주됩니다.

그 이유는이 언어와 다른 동기 데이터 흐름 언어가 과거에 대해 간결한 구문을 가지고 있기 때문입니다. 향후 사이클에서 필요한 경우 각 지점을 계산해야합니다. 언어는 기능적이어야하므로 중요하지는 않지만 C 기능을 호출 할 수 있습니다 (아마도 생각보다 자주 호출됩니다).

광택에서는 등가물을 작성합니다

if (y <> 0) then 100/y else 100

전형적인 초보자 실수입니다. 표현 100/y는 y = 0 일 때 사이클에서도 평가되기 때문에 0에 의한 분할은 피하지 않습니다.

단락으로 인해 응용 프로그램의 동작이 변경 될 수 있으므로 다음과 같습니다.

if(!SomeMethodThatChangesState() || !SomeOtherMethodThatChangesState())

가독성 문제에 유효하다고 말하고 싶습니다. 누군가가 명백한 방식으로 단락 평가를 활용하는 경우 관리자가 동일한 코드를보고 논리를 이해하기가 어려울 수 있습니다.

메모리가 제공되면 Erlang은 표준 및/또는 Andalso/orelse의 두 가지 구성을 제공합니다. 이것은 '예, 이것이 짧은 회로라는 것을 알고 있으며, 다른 점에서와 같이 코드에서 의도를 도출해야한다는 것을 명확하게합니다.

예를 들어, 관리자가 다음과 같은 라인을 만난다 고 가정 해보십시오.

if(user.inDatabase() || user.insertInDatabase()) 
    user.DoCoolStuff();

의도가 "사용자가 데이터베이스에 있지 않은 경우, 그/그녀를 삽입하십시오. 그것이 작동하는 경우 멋진 물건을 삽입한다"는 것을 인식하는 데 몇 초가 걸립니다.

다른 사람들이 지적했듯이, 이것은 부작용으로 일을 할 때만 실제로 관련이 있습니다.

나는 성능 문제에 대해 잘 모르지만 그것을 피할 수있는 한 가지 가능한 주장 (또는 적어도 과도한 사용)은 5월 다른 개발자를 혼동하십시오.

부작용 문제에 대해 이미 큰 응답이 있지만 질문의 성능 측면에 대해서는 아무것도 보지 못했습니다.

단락 평가를 허용하지 않으면 성능 문제는 결과가 변경되지 않더라도 양측을 평가해야한다는 것입니다. 이것은 일반적으로 문제가되지 않지만이 두 상황 중 하나에서 관련 될 수 있습니다.

  • 코드는 매우 자주 호출되는 내부 루프에 있습니다.
  • 표현식 평가와 관련된 높은 비용이 있습니다 (아마도 IO 또는 값 비싼 계산)

단락 평가는 발현의 일부에 대한 조건부 평가를 자동으로 제공합니다.

주요 장점은 표현을 단순화한다는 것입니다.

성능은 향상 될 수 있지만 매우 간단한 표현에 대한 페널티를 관찰 할 수도 있습니다.

또 다른 결과는 발현 평가의 부작용이 영향을받을 수 있다는 것이다.

일반적으로 부작용에 의존하는 것은 좋은 관행이 아니지만 일부 특정 상황에서는 선호되는 솔루션이 될 수 있습니다.

VB6은 단락 평가를 사용하지 않으며 최신 버전이 있는지는 모르겠지만 의심합니다. 나는 이것이 오래된 버전이 아니었기 때문이라고 생각하며, VB6을 사용한 대부분의 사람들은 그 일이 일어나기를 기대하지 않기 때문에 혼란을 초래할 것입니다.

이것은 스파게티 코드를 작성하고 내 여정을 시작한 멍청한 VB 프로그래머가되지 않는 것이 매우 어려운 것 중 하나 일뿐입니다. 진짜 프로그램 제작자.

많은 답변이 부작용에 대해 이야기했습니다. 다음은 부작용이없는 파이썬 예입니다. (내 의견으로는) 단락이 가독성을 향상시킵니다.

for i in range(len(myarray)):
  if myarray[i]>5 or (i>0 and myarray[i-1]>5):
    print "At index",i,"either arr[i] or arr[i-1] is big"

짧은 회로는 우리가 MyArray [-1]에 액세스하려고 시도하지 않도록합니다. Python 어레이는 0에서 시작하기 때문에 예외가 발생합니다. 코드는 물론 짧은 회로없이 작성 될 수 있습니다.

for i in range(len(myarray)):
  if myarray[i]<=5: continue
  if i==0: continue
  if myarray[i-1]<=5: continue
  print "At index",i,...

그러나 단락 버전은 더 읽기 쉬운 것 같습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top