Чому мови не включають значення як логічний оператор?


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

Це може бути корисно інколи, без сумніву. Проти такого оператора заперечують декілька пунктів:

  • Характери -і >цінні, як ізольовано, так і поєднані. Багато мов уже використовують їх для позначення інших речей. (І багато хто не може використовувати набори символів unicode для свого синтаксису.)
  • Наслідки є дуже протиінтуїтивними, навіть для логічно налаштованих людей, таких як програмісти. Той факт, що три з чотирьох записів таблиці істинності trueвикликає здивування багатьох.
  • Усі інші логічні оператори симетричні, що могло б зробити ->виняток з ортогональності.
  • У той же час існує просте вирішення: використовувати оператори !та ||.
  • Імплікація використовується набагато рідше, ніж логічна and/ or.

Можливо, тому оператор сьогодні рідкісний. Звичайно, це може стати більш поширеним, оскільки нові динамічні мови використовують Unicode для всього, а перевантаження оператора знову стає модною.


22
Ваш перший пункт лише заперечує проти використання "->" як символу для оператора, а не проти того, щоб насправді мати оператор. Інші - хороші моменти.
AShelly

14
"У той же час існує легке вирішення: використання! І &&.": Насправді найпростіший спосіб імітації "->" (або "=>", як це звичайніше в Math) - це використовувати !і ||, не !і &&: A -> Bеквівалентно тому, !A || Bщо еквівалентно !(A && !B).
Джорджіо

22
"Те, що три з чотирьох записів таблиці правди є справжніми, дивує багатьох людей". Ват. Я знаю іншого оператора з тією ж особливістю, який використовується досить часто ...
l0b0

9
@ l0b0, я програміст, який вивчав CS, але це було дуже давно. Я забув, що "мається на увазі" - це формальна операція з двома операндами, яка повертає значення істини, тому спочатку мене розгубила суть цього питання. У повсякденному мовленні я коли-небудь використовую "мається на увазі", коли перший операнд уже відомий як істинний ("X є істинним, тому Y повинен бути істинним"). Через хвилину я згадав, як формально "натякає" на роботу, але факт залишається фактом - навіть для того, хто колись вивчав формальну логіку, наміри були мені не зрозумілі. І якби я ніколи цього не вивчав, це не мало б навіть зрештою сенсу.
Бен Лі

5
(а) В C -> використовується як оператор. На це ніхто не скаржиться. Я б використовував => все одно. (б) Контрінтуїтивне для кого? Визначення імплікації - саме це, визначення. (c) віднімання не є комутативним. На це ніхто не скаржиться. (г) Я думаю, ти маєш на увазі! та || Через пріоритет (і) також часто потрібні. Цей же аргумент може бути використаний проти && або ||; взяти свій вибір. (е) Можливо, це тому, що його немає в більшості мов. Багато застосувань || може бути стисло і (як мінімум) інтуїтивно замінено імплікацією.
Теодор Норвелл

54

Я вважаю, що відповідь лежить у математичних засадах . Наслідки зазвичай розглядаються і визначаються як похідна, не елементарна, операція булевих алгебр. Мови програмування дотримуються цієї конвенції.

Це пропозиція I глави II з " Дослідження законів думки Джорджа Була" (1854) :

Усі операції з мовою як інструмент міркування можуть здійснюватися системою знаків, що складається з таких елементів, а саме:

1-й. Буквальні символи, як x, y та c., Представляють речі як предмети наших уявлень.

2-й. Ознаки дії, як +, -, ×, стоять для тих операцій розуму, за допомогою яких уявлення про речі поєднуються або вирішуються так, щоб утворювати нові уявлення, що включають ті ж елементи.

3-й. Знак тотожності, =.

І ці символи Логіки у своєму використанні підлягають певним законам, частково узгоджуючись і частково відрізняючись від законів відповідних символів у науці про Алгебру.

Знак Була + являє собою ту саму "операцію з розумом", яку ми сьогодні визнаємо як булевою "чи", так і об'єднанням множин. Аналогічно знаки - і × відповідають нашому булевому запереченню, доповненню множини, булевому «і» та перетину множин.


+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 вводить вас у сферу езотеричних мов (що дивовижно підходить, враховуючи ім’я користувача відповідателя ;-)).
Стефан Маєвський

1
@Stefan: Ви також можете отримати все від IMPL.
Мейсон Уілер

37

ОНОВЛЕННЯ: Це питання було предметом мого блогу в листопаді 2015 року . Дякую за цікаве запитання!


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

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

Ви згадали мови, схожі на С Я не можу спілкуватися з C або C ++ або Java, але можу говорити на C #. Існує список запропонованих користувачем функцій для C # буквально довше, ніж ваша рука. Наскільки мені відомо, жоден користувач ніколи не пропонував такого оператора команді C #, і я переглядав цей список багато, багато разів.

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


IMP повертається як оператор до GWBASIC днів. Я пам’ятаю це з 1979 року.
zarchasmpgmr

1
Я читав, що IMPL дуже корисний для кодових контрактів. (У якого не було VB.)
Мейсон Уілер

3
Програмісти VBScript були, ймовірно, групою, що найменш імовірно використовує такого оператора. Мені зараз хочеться, щоб у PowerShell був оператор, що передбачає, щоб я міг легше та чіткіше реалізувати деякі [switch]параметри фільтра.
бріанарі

Я пам’ятаю IMP від ​​DEC BASIC. Я не пам'ятаю EQV. Оператор, якого я часто бажав, був би "а не", який би сприяв правому оператору, перш ніж його відкидати. Таким чином, 0xABCD12345678ul ~& 0x00200000uвийде 0xABCD12145678ul, а не 0x12145678ul.
supercat

19

Я можу лише здогадуватися, але причиною може бути те, що існують обхідні шляхи, які є досить простими і зрозумілими. Розглянемо ваш приклад:

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

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

Якщо вам потрібен вираз, може бути використаний оператор вбудованого інтерфейсу, який доступний на більшості мов (його часто називають потрійним оператором). Зрозуміло, це не так елегантно A --> B, але кількість випадків використання може не виправдати додавання (та підтримку!) Іншого оператора:

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

2
Щодо тверджень - є вагомі причини. Перший створить (у багатьох реалізаціях) повідомлення "неудача ствердження: iv! = Null", а друге "помилка твердження: режим! = ECB -> iv! = Null".
Maciej Piechotka

2
+1, я збирався поставити це саме питання щодо запитання (оскільки я не дуже знайомий із "наслідком", він ніколи не виникає щодня). Це ifтвердження набагато зрозуміліше для всіх.
Ізката

12

Ейфель має наслідки

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

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

Виявляється, що коли ти володієш мовою з такими булевими операторами і знаєш, як з ними конструювати та використовувати, то ти їх використовуєш.

В Ейфелі використання ключового слова "мається на увазі" є досить помітним через проектування за контрактом через булевий характер контрактних тверджень. Існують деякі договори, які можна правильно та ефективно скласти лише з оператором "передбачає". Потім напрошується зауважити, що мови без контрактів надалі без приводу шукати, навчати та застосовувати використання наслідків.

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

Натомість людям-компіляторам необхідно створити резервну копію теорії, написати мовну нотацію, яку теорія пропонує чи передбачає (наприклад, Об'єктно-орієнтована теорія) незалежно від того, що думають чи просять немиті маси програмістів. Звідти професорам, викладачам та іншим професіоналам потрібно професійно навчати молодих мухоморів, заснованих на сирій теорії, а НЕ "теорії через мову". Коли це станеться, люди раптом прокинуться і зрозуміють, чого вони пропустили і що на них сфокусовано.

Наразі - існує стільки теорії, яка маскується під об'єктно-орієнтований, але це просто OO-через-склянку-темно-на- [вибери свою мову]. Не можна читати більшість «теоретичних» книг про ОО, оскільки вони хочуть інтерпретувати те, що ця теорія є через об'єктив якоїсь мови. Повністю помилкові та невірні. Це було б як викладання математики на основі мого калькулятора чи мого правила слайдів. НІ - дозволяє дійсності навчити себе про себе, а потім використовує позначення для опису того, що спостерігається - це називається "наука". Цей інший маш, який називається OO на основі мови-X, настільки перекошений, що ледве представляє реальність.

Отже, відійдіть від мови, погляньте на сиру теорію і почніть знову. Не дозволяйте обмеженням, обмеженням і фарбам завдань мови говорити про те, що таке теорія. Просто нехай реальність теорії диктує власне позначення, а потім перейдемо звідти до формулювання мови.

Звідти ви почнете отримувати, як підказки та "натяки" не тільки корисні, але й елегантні та дуже класні!

Майте чудовий!


7

У Python є оператор імплікації якось прихованим чином.

Оператор, менший за рівний або рівний, перевантажений, щоб прийняти булеві значення. Як результат, можна використовувати його в якості оператора імплікацій.

Доказ на прикладі (Python Code):

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()в цьому випадку.
Джон Перді

2
@Jon Purdy - Строго кажучи, оцінка короткого замикання є необов'язковою особливістю двійкових операторів. Технічно це абсолютно законна реалізація оператора імпліцитів. Якщо говорити, я дуже сумніваюся, що Гідо ван Россум навіть задумав це зробити оператором наслідків. Це лише химерність порівняння булей.
Mackenzie

Звичайно, я казав, що це цікаве спостереження, але не те, що ви повинні використовувати в реальних програмах, оскільки це не коротке замикання, і це може когось здивувати, якщо вони очікують did_all_possible_stuff = x.do_required_stuff() and (x.supports_optional_stuff() <= x.do_optional_stuff())на роботу.
Джон Перді

2
Це працює і в C, і C ++.
Бен Войгт

5

У Ейфеля є оператор "мається на увазі", і це дуже приємно для написання попередніх та постумов. Це робить код більш читабельним, на жаль, що ніколи не було принциповим наміром для мови на зразок C, і надто мало людей використовували ейфель, тому краса "передбачає", як оператор недостатньо відомий.


2

Для мене велика проблема із наслідками виникає тоді, коли початкова умова хибна; наприклад: "Якщо сонце зелене, то я - фруктова кажан". Правда!

У формальній логіці він просто працює, щоб призначити "True" значенням, коли умова імплікації не виконується. Але в програмуванні це може призвести до контрінтуїтивних та дивних результатів.

Я насправді думаю, що приклад @Heinzi дає вище:

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

Значно простіше зрозуміти і менш схильний до помилок через нерозуміння логіки.

У контексті тестування я просто зупинив момент, коли мої припущення стали помилковими:

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

Тож, на думку @Eric Lippert, як програміста я не знаю, коли б я використовував оператора, що має на увазі. Поведінка "Неправдива правда" здається корисною в контексті математичної, формальної логіки, але може призвести до несподіваних результатів у логіці програми.

...

Ніхто не згадав загальне "?" оператор, де "A? B: true" - це те саме, що "має на увазі". Але поки формальна логіка привласнює істину умові "else", "?" дозволяє розробнику явно призначити це.

У формальній логіці використання "true" працює, але в програмуванні, якщо умова хибна, то краща відповідь більше схожа на "null" або "void" або "skip", а може бути, і false.

Я думаю, що комусь доведеться зробити випадок, чому "мається на увазі" є більш корисним оператором, ніж заяви "?" Або "якщо", або просто регулярний потік програми.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.