Почему языки не включают импликацию как логический оператор?

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, в свою очередь, его нет, потому что это не является общей частью языка ассемблера. В то время как все известные мне наборы инструкций включают и, или нет, я не знаю ни одного, включающего в себя, подразумевает - несомненно, кто-то будет рядом, чтобы рассказать мне о каком-то непонятном наборе инструкций, который вскоре ...
Джек Эйдли,
4
Возможно, это было сочтено излишним, потому что (1) он менее примитивен, чем «^», «v», «~», (2) он экономит очень мало времени при наборе текста, поскольку «A => B» эквивалентно «~ A v B» ,
Джорджио
4
Языки, которые имеют дело с логическими конструкциями, имеют больше шансов иметь его. Главным среди них является пролог
9
Я удивлен, что вы думаете, что assert№ 1 яснее, чем № 2. Некоторое время я смотрел на # 1 и до сих пор не понимаю, как его поведение можно считать интуитивным. (особенно с дополнительным !=переключением логики)
Крис Берт-Браун

Ответы:

61

Это может быть полезно иметь иногда, без сомнения. Несколько аргументов против такого оператора:

  • Персонажи -и >являются ценными, как в отдельности, так и в сочетании. Многие языки уже используют их для обозначения других вещей. (И многие не могут использовать наборы символов Юникода для своего синтаксиса.)
  • Импликация очень нелогична даже для логически настроенных людей, таких как программисты. Тот факт, что три из четырех записей таблицы истинности являются trueудивительными для многих.
  • Все остальные логические операторы симметричны, что сделало бы ->исключение ортогональности.
  • В то же время существует простой обходной путь: используйте операторы !и ||.
  • Импликация используется значительно реже, чем логическая and/ or.

Вероятно, поэтому оператор сегодня встречается редко. Конечно, это может стать более распространенным, так как новые динамические языки используют Unicode для всего, и перегрузка операторов снова становится более модной.

Килиан Фот
источник
22
Ваша первая точка зрения только против использования «->» в качестве символа для оператора, а не против фактического наличия оператора. Другие хорошие моменты.
AShelly
14
«В то же время, существует простой обходной путь: используйте! И &&.»: На самом деле, самый простой способ имитации «->» (или «=>», как это чаще встречается в Math), это использовать !а ||не !и &&: A -> Bэквивалентно тому, !A || Bчто эквивалентно !(A && !B).
Джорджио
22
«Тот факт, что три из четырех записей таблицы истинности являются истинными, удивляет многих». Wat. Я знаю другого оператора с такой же функцией, который используется довольно часто ...
l0b0
9
@ l0b0, я программист, который изучал CS, но это было давно. Я забыл, что «подразумевает» - это формальная операция с двумя операндами, которая возвращает значение истинности, поэтому сначала я был озадачен природой этого вопроса. В повседневной речи я всегда использую «подразумеваемый», только когда первый операнд уже известен как истинный («X является истинным, поэтому Y должен быть истинным»). Через минуту я вспомнил, как работает формальное «подразумеваемое», но факт остается фактом - даже для того, кто когда-то изучал формальную логику, цель не была мне ясна. И если бы я никогда не изучал это, это даже не имело бы смысла.
Бен Ли
5
(а) В C -> используется как оператор. Никто не жалуется на это. Я бы использовал => в любом случае. (б) Противоинтуитивно для кого? Определение импликации - это просто определение. (в) вычитание не является коммутативным. Никто не жалуется на это. (г) я думаю, что вы имеете в виду! и || Из-за приоритета (и) часто также необходимы. Тот же аргумент может быть использован против && или ||; сделайте ваш выбор. (д) Возможно, это потому, что это не на большинстве языков. Многие использования || может быть кратко и (по крайней мере для меня) интуитивно заменено импликацией.
Теодор Норвелл
54

Я считаю, что ответ лежит в математических основах . Импликация обычно рассматривается и определяется как производная, а не элементарная операция булевых алгебр. Языки программирования следуют этому соглашению.

Это предложение I главы II из книги Джорджа Буля « Исследование законов мышления» (1854) :

Все операции языка, как инструмент рассуждения, могут проводиться системой знаков, состоящей из следующих элементов, а именно:

Первый. Буквенные символы, такие как х, у и т. Д., Представляющие вещи как предметы наших концепций.

Второй. Признаки действия, такие как +, -, ×, обозначают те действия разума, с помощью которых концепции вещей объединяются или разрешаются, образуя новые концепции, включающие одни и те же элементы.

Третий. Знак идентичности, =.

И эти символы логики в своем использовании подчиняются определенным законам, частично согласующимся и частично отличающимся от законов соответствующих символов в науке об алгебре.

Знак + логического выражения представляет ту же самую «операцию разума», которую мы сегодня признаем как логическое «или» и объединение множеств. Точно так же знаки - и × соответствуют нашему логическому отрицанию, дополнению множества, логическому «и» и пересечению множеств.

РОДОМ ИЗ
источник
+1 - солидный ответ. Булева алгебра и упрощения в логике, которые она допускает, основаны на методологии программирования. Использование «подразумевает ...» потенциально может повлиять на условия «все равно».
3
1. Это зависит от определения. Можно определить или как a || b = !(!a && !b)(я встречал или как производный оператор по логике). 2. Причина, по которой это делается, состоит в том, чтобы, как я полагаю, упрощать индукционные доказательства (мы знаем, что производные операторы являются просто сокращенными, поэтому нам не нужно иметь отдельный случай для них). @ GlenH7: Какие "пофиг" условия? a --> bтак же, как !a || b.
Мацей Пехотка
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 ставит вас в область эзотерических языков (что удивительно хорошо подходит, учитывая имя пользователя ответчика ;-)).
Стефан Маевский
1
@Stefan: Вы также можете получить все из IMPL.
Мейсон Уилер
37

ОБНОВЛЕНИЕ: Этот вопрос был темой моего блога в ноябре 2015 года . Спасибо за интересный вопрос!


Visual Basic 6 (и VBScript) имел Impи Eqvоператоры. Никто не использовал их. Оба были удалены в VB.NET; Насколько мне известно, никто не жаловался.

Я работал в команде компилятора Visual Basic (в качестве стажера) целый год и ни разу не заметил, что у VB даже были эти операторы. Если бы я не был парнем, пишущим компилятор VBScript, и поэтому должен был бы протестировать их реализации, я, вероятно, не заметил бы их. Если парень из команды компиляторов не знает о функции и не использует ее, это говорит вам о популярности и полезности этой функции.

Вы упомянули C-подобные языки. Я не могу говорить с C или C ++ или Java, но я могу говорить с C #. Существует список предлагаемых пользователем функций для C # буквально длиннее вашей руки. Насколько мне известно, ни один пользователь никогда не предлагал такой оператор команде C #, и я просматривал этот список много, много раз.

Возможности, которые существуют и не используются на одном языке и никогда не запрашиваются на другом языке, вряд ли могут быть использованы в современных языках программирования. Особенно, когда в бюджете не хватает времени, сил и денег для создания функций, которые действительно нужны людям .

Эрик Липперт
источник
IMP возвращается в качестве оператора GWBASIC дней. Я помню это с 1979 года.
zarchasmpgmr
1
Я читал, что IMPL очень полезен для контрактов кода. (Которого у В.Б. не было.)
Мейсон Уилер
3
Программисты VBScript, вероятно, были группой, которая реже всего использовала такой оператор. Сейчас я хочу, чтобы в PowerShell был оператор implies, чтобы я мог проще и понятнее реализовать некоторые [switch]параметры фильтра.
brianary
Я помню IMP из DEC BASIC. Я не помню EQV. Оператор, которого я часто желал, был бы «а не», что продвигало бы правого оператора, прежде чем отрицать его. Таким образом, 0xABCD12345678ul ~& 0x00200000uвыдаст 0xABCD12145678ul, а не 0x12145678ul.
суперкат
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);
Heinzi
источник
2
По утверждению - есть веская причина. Первая выдаст (во многих реализациях) сообщение «Ошибка подтверждения: iv! = Null», а вторая «Ошибка подтверждения: режим! = ECB -> iv! = Null».
Мацей Печотка
2
+1, я собирался задать то же самое в вопросе (поскольку я не очень знаком с «подтекстом», он никогда не приходит в голову изо дня в день). Это ifутверждение намного, намного понятнее почти всем.
Изката
12

Эйфелева имеет значение

На самом деле есть даже больше. У этого есть много полужестких операторов так же как строгих.

Причина, по которой программисты не используют такие вещи, заключается в том, что их никогда не учили точно знать, кто они такие, как их использовать и когда их использовать, а также как их проектировать. Поскольку они никогда не обучаются, они никогда не просят об этом у авторов компиляторов, поэтому люди, занимающиеся компиляцией, не заботятся о том, чтобы помещать такие механизмы в компилятор. Когда студенты-информатики и программисты Shade-Tree начнут получать более округлое образование, компиляторы начнут наверстывать упущенное.

Оказывается, если у вас есть язык с такими булевыми операторами, и вы знаете, как проектировать их и использовать их, тогда вы их используете.

В Eiffel использование ключевого слова «подразумевает» является довольно заметным из-за Design-by-Contract из-за булево-тяжелого характера утверждений контракта. Есть некоторые контракты, которые могут быть написаны правильно и эффективно только с оператором «подразумевает». Затем напрашивается комментарий о том, что языки без контрактов не имеют смысла смотреть, обучать и реализовывать использование импликации.

Добавьте к этому, что большинство программистов, «слабо разбирающихся в математике и логике», рассказывает нам об остальной части истории. Даже если в вашем образовании вы увлечены математикой и логикой, когда выбираете язык, в котором не реализованы такие конструкции, как импликация, вы склонны считать, что такие вещи не нужны или не полезны. Один редко подвергает сомнению язык и попадает в эхо-камеру: «Ну, ребята из компилятора не видят необходимости» и «Ну, программисты не видят необходимости» - бесконечный и замкнутый круг.

Вместо этого люди, работающие с компилятором, должны вернуться к теории, написать обозначение языка, которое предлагается или подразумевается теорией (например, объектно-ориентированная теория), независимо от того, что думают или просят немытые массы программистов. Оттуда профессорам, учителям и другим специалистам необходимо профессионально обучать молодых людей, основанных на необработанной теории, а не на «теории через линзу языка». Когда это происходит, люди внезапно просыпаются и осознают, чего им не хватало и что им навязали.

Прямо сейчас - существует так много теории, которая маскируется под Объектно-Ориентированную, но это просто "сквозь стекло, мрачно-оф-твои". Никто не может прочитать большинство «теоретических» книг по ОО, потому что они хотят интерпретировать, что такое теория, через призму какого-то языка. Совершенно неверно и неверно. Это все равно что учить математике на калькуляторе или правилам скольжения. НЕТ - человек позволяет реальности учить себя самому, а затем использует нотацию для описания того, что он наблюдает - это называется «наука». Эта другая смесь, называемая OO-based-on-language-X, настолько искажена, что едва ли представляет реальность.

Итак, отойдите от языка, взгляните на грубую теорию и начните снова. Не позволяйте ограничениям, ограничениям и рисованиям языка говорить вам, что такое теория. Просто позвольте реальности теории диктовать свои собственные обозначения, а затем перейти к формулировке языка.

Оттуда вы начнете понимать, как подтекст и «намеки» не только полезны, но и элегантны и очень круты!

Хорошего вам!

Larry
источник
7

У Python есть оператор импликации в некотором скрытом виде.

Оператор «меньше или равно» перегружен для принятия логических значений. В результате его можно использовать как оператор импликации.

Доказательство примером (код Python):

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
Mackenzie
источник
2
Это потрясающе, но, к сожалению, имеет неправильные свойства строгости: f() implies g()не следует оценивать, g()если f()есть False, но <=оценивает g()в этом случае.
Джон Перди
2
@Jon Purdy - Строго говоря, оценка короткого замыкания является дополнительной функцией бинарных операторов. Технически, это совершенно законная реализация имплицитного оператора. При этом я действительно сомневаюсь, что Гвидо ван Россум даже намеревался сделать это имплицитным оператором. Это просто причуда сравнения логических значений.
Маккензи
Конечно, я говорил, что это интересное наблюдение, но не то, что вы должны использовать в реальных программах, потому что оно не имеет короткого замыкания и может застать кого-то врасплох, если он рассчитывает did_all_possible_stuff = x.do_required_stuff() and (x.supports_optional_stuff() <= x.do_optional_stuff())на работу.
Джон Пурди
2
Это работает и в C и C ++.
Бен Фойгт
5

У Eiffel есть оператор «подразумевает», и он очень хорош для написания предварительных и постусловий. Это делает код более читабельным, к сожалению, это никогда не было фундаментальным намерением для языка, подобного 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» совпадает с «подразумевает». Но в то время как формальная логика присваивает true условию else, «?» позволяет разработчику назначить это явно.

В формальной логике использование «true» работает, но в программировании, если условие ложно, тогда лучший ответ больше похож на «null» или «void», или «skip», или даже может быть false.

Я думаю, что кто-то должен был бы объяснить, почему «подразумевает» более полезный оператор, чем операторы «?» Или «если», или просто обычный программный поток.

обкрадывать
источник