언어에 논리 연산자로서의 의미가 포함되지 않는 이유는 무엇입니까?


60

이상한 질문 일지 모르지만 많은 언어 (Java, C, C ++, Python Haskell에서 논리 연산자로 의미가없는 이유는 무엇입니까? 마지막으로 사용자가 연산자를 추가하여 사소한 것으로 정의했지만)? 논리적 의미는 (특히 주장이나 주장과 같은 표현으로) 작성하는 것이 훨씬 명확하다는 것을 알 수 있습니다.

encrypt(buf, key, mode, iv = null) {
    assert (mode != ECB --> iv != null);
    assert (mode == ECB || iv != null);
    assert (implies(mode != ECB, iv != null)); // User-defined function
}

28
C에 넣지 않았기 때문에; C ++, Java 및 C #에 넣었다면 가능했을 것입니다.
m3th0dman

4
그러나 C는 어셈블리 언어의 일반적인 부분이 아니기 때문에 그것을 가지고 있지 않습니다. 내가 아는 모든 지시 세트는 포함하거나 포함하지 않는 것을 암시하지만, 포함하는 것이 없다는 것을 알고 있습니다. 의심 할 여지없이 누군가가 곧 알려지지 않은 지시 세트를 알려줄 것입니다.
Jack Aidley

4
아마도 (1) ​​"^", "v", "~"보다 원시적이지 않기 때문에 중복으로 간주되었을 수 있습니다. (2) "A => B"가 "~ A v B"와 같기 때문에 타이핑이 거의 없습니다. .
Giorgio

4
논리적 구조를 다루는 언어가 그럴 가능성이 높습니다. 이들 중 주로 프롤로그

9
assert# 1이 # 2보다 명확 하다고 생각 합니다. 나는 # 1을 한동안 쳐다 보았지만 여전히 그 동작이 직관적이라고 생각되는 방법을 볼 수 없습니다. (특히 여분 !=의 논리를 뒤집어
Chris Burt-Brown

답변:


61

때로는 의심의 여지가없는 것이 유용 할 수 있습니다. 여러 가지 요점이 그러한 연산자에 반대합니다.

  • 문자는 ->분리와 결합 모두 가치가있다. 많은 언어가 이미 다른 것을 의미하기 위해 사용합니다. (많은 사람들이 구문에 유니 코드 문자 집합을 사용할 수 없습니다.)
  • 프로그래머와 같은 논리적 인 사람들에게도 직관은 매우 직관적입니다. 4 개의 진리표 항목 중 3 개가 true많은 사람들에게 놀라운 사실입니다.
  • 다른 모든 논리 연산자는 대칭이므로 ->직교성을 제외합니다.
  • 연산자를 사용 : 동시에, 쉬운 해결 방법은 !||.
  • 의미는 논리적 and/ 보다 훨씬 덜 자주 사용됩니다 or.

이것이 오늘날 운영자가 드문 이유입니다. 새로운 동적 언어가 모든 것에 유니 코드를 사용하고 연산자 오버로드가 다시 유행에 따라 더 일반적이 될 수 있습니다.


22
첫 번째 요점은 실제로 연산자를 갖는 것이 아니라 '->'를 연산자의 상징으로 사용하는 것에 반대합니다. 다른 좋은 점입니다.
AShelly

14
"동시에, 쉬운 해결 방법이 있습니다 : use! and &&.": 실제로 "->"(또는 "=>"를 수학에서 가장 일반적으로 시뮬레이션하는 가장 간단한 방법은 사용하는 것입니다) !그리고 ||,하지 !&&: A -> B에 해당 !A || B에 해당한다 !(A && !B).
Giorgio

22
"4 개의 진리표 항목 중 3 개가 사실이라는 사실은 많은 사람들에게 놀라운 일입니다." 왓. 나는 자주 사용되는 동일한 기능을 가진 다른 연산자를 알고있다.
l0b0

9
@ l0b0, 저는 CS를 공부 한 프로그래머이지만 오래 전입니다. "암시"는 진리 값을 반환하는 두 개의 피연산자가있는 공식적인 작업이라는 것을 잊었으므로 처음에는이 질문의 본질에 혼란 스러웠습니다. 일상 연설에서, 나는 첫 번째 피연산자가 이미 참인 것으로 알려진 경우에만 "암시"를 사용합니다 ( "X는 참이므로 Y는 참이어야합니다"). 잠시 후, 나는 공식적인 "의미"의 작동 방식을 기억했지만 사실 공식 논리를 공부 한 사람조차도 그 의도는 명확하지 않았다. 그리고 내가 그것을 공부 한 적이 없다면, 결국에는 의미가 없었을 것입니다.
Ben Lee

5
(a) C에서->는 연산자로 사용됩니다. 아무도 그것에 대해 불평하지 않습니다. 어쨌든 =>를 사용합니다. (ᄂ) 누구에게 반 직관적입니까? 함의의 정의는 바로 그 정의입니다. (c) 빼기는 정류가 아니다. 아무도 그것에 대해 불평하지 않습니다. (d) 나는 당신이 의미하는 것 같아요! 그리고 ||. 우선 순위 (및)도 종종 필요합니다. && 또는 ||에 대해 동일한 인수를 사용할 수 있습니다. 골라보세요. (e) 아마도 대부분의 언어가 아니기 때문일 수 있습니다. ||의 많은 용도 간결하고 (적어도) 직관적으로 의미로 대체 될 수 있습니다.
Theodore Norvell

54

답은 수학적 기초 에 있다고 생각합니다 . 일반적으로 의미는 기본이 아닌 부울 대수의 파생 된 연산으로 간주되고 정의됩니다. 프로그래밍 언어는이 규칙을 따릅니다.

이것은 George Boole의 ' 사고의 법칙 조사 (1854) '제 2 장 발의안 제 1 호입니다 .

추론의 도구로서 언어의 모든 작업은 다음 요소로 구성된 표시 시스템에 의해 수행 될 수 있습니다.

1 일 우리의 개념의 주제로 사물을 나타내는 x, y, & c.와 같은 문자 기호.

2 일. +,-, ×와 같은 작동 신호는 동일한 요소를 포함하는 새로운 개념을 형성하기 위해 사물의 개념이 결합되거나 해결되는 마음의 작동을 나타냅니다.

셋째. 정체성의 표시, =.

그리고 이러한 논리의 상징은 대수학의 과학에서 해당 상징의 법에 부분적으로 동의하고 부분적으로 다른 명확한 법칙에 따라 사용됩니다.

Boole의 부호 +는 오늘날 우리가 부울 'or'와 집합의 결합으로 인식하는 것과 동일한 "마음의 조작"을 나타냅니다. 마찬가지로 부호-및 ×는 부울 부정, 집합의 보완, 부울 '및'및 집합의 교차에 해당합니다.


+1-확실한 답변. 부울 대수와 논리의 단순화로 인해 많은 프로그래밍 방법론이 가능합니다. "암시 ..."를 사용하면 잠재적으로 "무관심"조건을 방해 할 수 있습니다.

3
1. 그것은 정의에 달려 있습니다. 또는로 정의 할 수 있습니다 a || b = !(!a && !b)(논리에서 충족되거나 파생 된 연산자로). 2. 그것이 수행되는 이유는 일반적으로 유도 유도를 단순화하기 위해서입니다. 우리는 파생 연산자가 지름길이라는 것을 알고 있으므로 별도의 사례가 필요하지 않습니다. @ GlenH7 : "무관심"조건은 무엇입니까? a --> b와 동일합니다 !a || b.
Maciej Piechotka

3
또한-우리는 xor ( !=) nxor ( ==) 와 같은 다른 파생 연산자를 가지고 있습니다 .
Maciej Piechotka

5
실제로 NAND !(a && b)또는 NOR 에서 모든 것을 파생시킬 수 있습니다 !(a || b). 예를 들어, NOT a == a NAND a, a AND b == NOT(a NAND b), a OR b == (NOT a) NAND (NOT b). 그러나 NAND 연산자 만 제공하면 난해한 언어의 영역에있게됩니다 (응답자의 사용자 이름 ;-)을 감안할 때 놀랍게도 잘 맞습니다).
Stefan Majewsky

1
@ 스테판 : 당신은 또한 IMPL에서 모든 것을 파생시킬 수 있습니다.
메이슨 휠러

37

업데이트 :이 질문은 2015 년 11 월 내 블로그의 주제였습니다 . 흥미로운 질문에 감사드립니다!


비주얼 베이직 6 (및 VBScript를)을 가지고 ImpEqv운영자. 아무도 사용하지 않았습니다. VB.NET에서 둘 다 제거되었습니다. 내 지식으로는 아무도 불평하지 않았다.

Visual Basic 컴파일러 팀 (인턴)에서 일 년 동안 일한 적이 있으며 VB에 이러한 연산자가 있다는 것을 한 번도 눈치 채지 못했습니다. VBScript 컴파일러를 작성하는 사람이 아니 었으므로 구현을 테스트해야했지만 아마도 눈치 채지 못했을 것입니다. 컴파일러 팀 의 담당자 가 기능에 대해 알지 못하고 사용하지 않으면 기능의 인기와 유용성에 대해 알려줍니다.

C와 같은 언어를 언급했습니다. C 또는 C ++ 또는 Java와는 대화 할 수 없지만 C #과는 대화 할 수 있습니다. C #에 대해 사용자가 제안한 기능 목록은 말 그대로 팔보다 길다. 내 지식으로는 C # 팀에 그러한 연산자를 제안한 사람이 없으며 그 목록을 여러 번 살펴 보았습니다.

한 언어로 존재하고 사용되지 않고 다른 언어로 요청되지 않는 기능은 현대 프로그래밍 언어로 만들 가능성이 낮습니다. 특히 예산에 사람들 원하는 기능을 만들기에 충분한 시간과 노력과 돈이 없을 때 .


IMP는 운영자로서 GWBASIC 일로 되돌아갑니다. 나는 1979 년부터 그것을 기억합니다.
zarchasmpgmr

1
IMPL이 코드 계약에 매우 유용하다는 것을 읽었습니다. (VB는 없었습니다.)
Mason Wheeler

3
VBScript 프로그래머는 아마도 그러한 연산자를 사용할 가능성이 가장 낮은 그룹 일 것입니다. PowerShell에 암시 연산자가있어 [switch]필터 매개 변수를 보다 쉽고 쉽게 구현할 수 있기를 바랍니다 .
brianary

DEC BASIC의 IMP를 기억합니다. 기억이 없습니다 EQV. 내가 종종 원했던 연산자는 "하지 않을 것"이며, 오른쪽 연산자 부정 하기 전에 승격시킬 것입니다. 따라서 0xABCD12345678ul ~& 0x00200000u0x12145678ul 대신 0xABCD12145678ul을 생성합니다.
supercat

19

나는 추측 할 수 있지만 그 이유는 매우 간단하고 읽기 쉬운 해결 방법이 있기 때문일 수 있습니다. 당신의 예를 생각해 봅시다 :

if (mode != ECB) assert (iv != null);

assert (mode != ECB --> iv != null);  // <-- that's only one character shorter

식이 필요한 경우 대부분의 언어로 제공되는 인라인 if 연산자 (일반적으로 삼항 연산자라고도 함)를 사용할 수 있습니다. 물론 이것은 우아 A --> B하지는 않지만 사용 사례 수가 다른 연산자를 추가하고 유지하는 것을 정당화하지 못할 수도 있습니다.

assert (mode != ECB ? iv != null : true);

2
주장대로-좋은 이유가 있습니다. 첫 번째는 (많은 구현에서) "어설 션 실패 : iv! = null"메시지를 생성하고 두 번째 "어설 션 실패 : 모드! = ECB-> iv! = null"메시지를 생성합니다.
Maciej Piechotka

2
+1, 나는이 질문에 대해 똑같은 질문을하려고하였습니다. ( "시사점"에 익숙하지 않기 때문에, 그것은 매일 일어나지 않습니다). if문은, 지금까지 거의 모든 사람에게 훨씬 더 명확하다.
Izkata

12

에펠은 의미가있다

실제로 훨씬 더 있습니다. 그것은 엄격한뿐만 아니라 많은 반 엄격한 연산자를 가지고 있습니다.

프로그래머가 그러한 것들을 사용하지 않는 이유는 그들이 무엇인지, 어떻게 사용하는지, 언제 사용하는지, 어떻게 디자인 하는지를 정확히 알도록 훈련받지 않았기 때문입니다. 그들은 결코 훈련을받지 않았기 때문에 컴파일러 작성자에게 요청하지 않기 때문에 컴파일러 사람들은 그러한 메커니즘을 컴파일러에 넣는 것을 귀찮게하지 않습니다. Computer Science 학생들과 Shade-tree 프로그래머가보다 둥근 교육을 받기 시작하면 컴파일러가 따라 잡기 시작합니다.

그런 부울 연산자를 가진 언어가 있고 그 언어를 사용하여 디자인하고 사용하는 방법을 알고 나면 사용하는 것으로 나타났습니다.

Eiffel에서는 계약 어설 션의 부울이 많은 특성으로 인해 계약 별 디자인으로 인해 "implies"키워드를 사용하는 것이 다소 두드러집니다. "묵시적"연산자를 사용하여 적절하고 효율적으로 만 작성할 수있는 일부 계약이 있습니다. 그런 다음 계약이없는 언어는 더 이상 함의 사용을보고, 훈련하고, 구현할 이유가 없다는 의견을 요구합니다.

이것에 덧붙여 대부분의 프로그래머들은 "수학적이고 논리적 인 약점"이라고 이야기의 나머지 부분을 알려줍니다. 당신이 당신의 교육에 수학과 논리가 무겁더라도, 함축과 같은 구문을 구현하지 않는 언어를 선택할 때, 그러한 것들이 불필요하거나 유용하지 않다고 생각하는 경향이 있습니다. 언어에 의문을 제기하는 사람은 거의 없으며 "컴파일러가 필요를 보지 못했음"과 "프로그래머가 필요를 보지 못했음"이라는 끝없는 악순환이됩니다.

대신에, 컴파일러 사람들은 이론으로 백업하고, 씻지 않은 많은 프로그래머들이 생각하거나 요구하는 것에 관계없이 이론에 의해 제안되거나 암시되는 언어 표기법을 작성해야한다 (예 : 객체 지향 이론). 거기에서 교수, 교사 및 기타 전문가들은 "언어 렌즈를 통한 이론"이 아닌 원시 이론을 기반으로 젊은 어리석은 사고를 전문적으로 훈련해야합니다. 이런 일이 발생하면 사람들은 갑자기 깨어나 무엇을 잃어 버렸는지, 무엇을 습격했는지 알게됩니다.

지금 당장-객체 지향과 같은 가장 무도회라는 이론이 많이 있지만, OO-glass-dark-of-[-pick-your-language]입니다. OO에 관한 대부분의 "이론"책은 어떤 언어의 렌즈를 통해 이론이 무엇인지 해석하기를 원하기 때문에 읽을 수 없습니다. 완전히 틀렸다. 수학 기반의 계산기 나 슬라이드 규칙을 가르치는 것과 같습니다. 아니요. 현실은 스스로에 대해 가르친 다음, "과학"이라고 불리는 것을 관찰하기 위해 표기법을 사용합니다. OO-based-on-language-X라는 다른 매쉬는 현실을 거의 나타내지 않도록 왜곡되어 있습니다.

따라서 언어에서 벗어나 원시 이론을 살펴보고 다시 시작하십시오. 언어의 한계, 제약 및 페인트 작업이 이론이 무엇인지 말하지 않도록하십시오. 단순히 이론의 현실이 자신의 표기법을 지시하게 한 다음 거기에서 언어를 공식화하는쪽으로 이동하십시오.

거기에서 함의와 "의미"가 유용 할뿐만 아니라 우아하고 매우 시원 할 수있는 방법을 얻게됩니다.

좋은 일이!


7

파이썬에는 일종의 숨겨진 방식으로 함축 연산자가 있습니다.

같거나 같지 않은 연산자는 부울 값을 허용하도록 오버로드됩니다. 결과적으로이를 함축 연산자로 사용할 수 있습니다.

예제로 증명 (파이썬 코드) :

print (False <= False) # This will print True.
print (False <= True)  # This will print True.
print (True <= False)  # This will print False.
print (True <= True)   # This will print True.

함축 연산자의 진리표는 다음과 같습니다.

LEFT RIGHT RESULT
F    F     T
F    T     T
T    F     F
T    T     T

2
이 굉장하지만, 불행히도 잘못된 엄격 성을 가지고 f() implies g()평가해서는 안 g()경우 f()입니다 False만, <=평가 않습니다 g()이 경우.
Jon Purdy

2
@Jon Purdy-엄밀히 말하면 단락 평가는 이진 연산자의 선택적 기능입니다. 기술적으로 이것은 함축 연산자를 완벽하게 합법적으로 구현 한 것입니다. 즉, 귀도 반 로섬 (Guido van Rossum)이 이것을 함의 연산자로 의도 한 것도 의심 스럽다. 이것은 부울을 비교하는 기발한 일입니다.
Mackenzie

물론, 나는 그것이 흥미로운 관찰이라고 말하고 있지만 실제 프로그램에서 사용해서는 안되는 것이 아닙니다. 단락이 아니기 때문에 누군가가 did_all_possible_stuff = x.do_required_stuff() and (x.supports_optional_stuff() <= x.do_optional_stuff())일할 것으로 예상되면 놀라게 할 수 있기 때문입니다 .
Jon Purdy

2
이것은 C 및 C ++에서도 작동합니다.
Ben Voigt

5

Eiffel에는 "implies"연산자가 있으며 사전 및 사후 조건을 작성하는 데 매우 좋습니다. 불행히도 코드는 C와 같이 언어와 같은 근본적인 강렬함이 아니었고 너무 적은 수의 사람들이 eiffel을 사용 했으므로 연산자로서 "암시"의 아름다움은 잘 알려져 있지 않습니다.


2

나에게있어 큰 문제는 초기 조건이 거짓 일 때 발생한다는 것이다. 예를 들어 "태양이 녹색이면 나는 과일 박쥐입니다." 참된!

공식적인 논리에서는 의미의 조건이 충족되지 않을 때 값에 "참"을 지정하는 것입니다. 그러나 프로그래밍에서 이는 직관적이고 놀라운 결과로 이어질 수 있습니다.

실제로 @Heinzi의 예가 위와 같이 생각합니다.

if (sun.color() == "green") then assert(me.species() == "fruitbat")

논리를 오해하여 이해하기가 훨씬 쉽고 오류가 적습니다.

테스트의 맥락에서, 나는 내 가정이 틀린 순간을 막을 것입니다.

assert(sun.color() == "green")
assert(me.species() == "fruitbat")

따라서 @Eric Lippert의 요점으로 프로그래머는 암시 연산자를 언제 사용할지 알 수 없습니다. "False is True"동작은 수학적, 형식적 논리와 관련하여 유용하지만 프로그램 논리에서 예기치 않은 결과를 초래할 수 있습니다.

...

아무도 일반적인 "?"에 대해 언급하지 않았습니다. 연산자, 여기서 "A? B : true"는 "implies"와 동일합니다. 그러나 공식적인 논리는 "else"조건 인 "?"에 적용됩니다. 개발자가 명시 적으로 할당하도록합니다.

공식적인 논리에서 "true"를 사용하면 문제가 해결되지만 프로그래밍에서 조건이 false이면 더 나은 대답은 "null"또는 "void"또는 "skip"또는 false 일 수 있습니다.

"암시"가 "?", "if"문 또는 정기적 인 프로그램 흐름보다 더 유용한 연산자 인 이유를 누군가가 판단해야한다고 생각합니다.


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