To może być dziwne pytanie, ale dlaczego w wielu językach (Java, C, C ++, Python Haskell - jako operator logiczny nie ma to żadnego znaczenia)? Uważam, że logiczna implikacja jest znacznie łatwiejsza do napisania (szczególnie w asercjach lub wyrażeniach podobnych do asercji), a następnie negacja za pomocą lub:
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
}
language-design
Maciej Piechotka
źródło
źródło
assert
# 1 jest jaśniejszy niż # 2. Przez jakiś czas wpatrywałem się w numer 1 i wciąż nie widzę, jak jego zachowanie można uznać za intuicyjne. (szczególnie z dodatkową!=
logiką)Odpowiedzi:
Przydałoby się czasem mieć bez wątpienia. Kilka argumentów przemawia przeciwko takiemu operatorowi:
-
i>
są cenne, zarówno w izolacji, jak i razem. Wiele języków używa ich już w znaczeniu innych rzeczy. (I wielu nie może używać zestawów znaków Unicode do ich składni.)true
zaskakuje wielu ludzi.->
wyjątek od ortogonalności.!
i||
.and
/or
.Prawdopodobnie dlatego operator jest dziś rzadkością. Z pewnością może stać się bardziej powszechny, ponieważ nowe dynamiczne języki używają Unicode do wszystkiego, a przeciążanie operatorów znów staje się bardziej modne.
źródło
!
oraz||
nie!
i&&
:A -> B
jest równoważne z tym,!A || B
co jest równoważne z!(A && !B)
.Wierzę, że odpowiedź leży w matematycznych podstawach . Implikacja jest zwykle rozpatrywana i definiowana jako pochodna, a nie elementarna operacja algebr boolowskich. Języki programowania są zgodne z tą konwencją.
Oto propozycja I rozdziału II z George'a Boole'a An Investigation of the Laws of Thought (1854) :
Znak Boole'a + reprezentuje tę samą „operację umysłu”, którą dzisiaj uznajemy za zarówno logiczny „lub”, jak i związek zbiorów. Podobnie znaki - i × odpowiadają naszej negacji boolowskiej, uzupełnieniu zbioru, wartości logicznej „i” oraz przecięciu zbiorów.
źródło
a || b = !(!a && !b)
(poznałem lub jako operator pochodny w logice). 2. Powodem, dla którego tak się dzieje, jest zwykle uproszczenie indukcji, jak sądzę (wiemy, że operatory pochodne są tylko skrótami, więc nie musimy mieć dla nich osobnego przypadku). @ GlenH7: Jakie warunki „nie obchodzi mnie”?a --> b
jest taki sam jak!a || b
.!=
) nxor (==
) ...!(a && b)
lub NOR!(a || b)
. Na przykładNOT a == a NAND a
,a AND b == NOT(a NAND b)
,a OR b == (NOT a) NAND (NOT b)
. Ale udostępnienie tylko operatora NAND umieszcza cię w dziedzinie ezoterycznych języków (co zaskakująco dobrze pasuje, biorąc pod uwagę nazwę użytkownika odpowiadającego ;-)).AKTUALIZACJA: To pytanie było przedmiotem mojego bloga w listopadzie 2015 r . Dzięki za interesujące pytanie!
Visual Basic 6 (i VBScript) miał
Imp
iEqv
operatory. Nikt ich nie używał. Oba zostały usunięte w VB.NET; według mojej wiedzy nikt nie narzekał.Przez cały rok pracowałem w zespole kompilatorów Visual Basic (jako stażysta) i nigdy nie zauważyłem, że VB ma nawet tych operatorów. Gdybym nie był facetem piszącym kompilator VBScript i dlatego musiałem przetestować ich implementacje, prawdopodobnie nie zauważyłbym ich. Jeśli facet w zespole kompilatorów nie wie o tej funkcji i jej nie używa, to mówi ci coś o popularności i przydatności tej funkcji.
Wspomniałeś o językach podobnych do C. Nie mogę mówić do C, C ++ lub Java, ale mogę mówić do C #. Istnieje lista funkcji sugerowanych przez użytkownika dla C # dosłownie dłuższych niż twoje ramię. Według mojej wiedzy, żaden użytkownik nigdy nie zaproponował takiego operatora zespołowi C #, a ja przeglądałem tę listę wiele, wiele razy.
Funkcje, które istnieją i są nieużywane w jednym języku, i nigdy nie są wymagane w innym, są mało prawdopodobnymi kandydatami do przejścia na nowoczesne języki programowania. Szczególnie, gdy nie ma wystarczająco dużo czasu i wysiłku i pieniędzy dostępnych w budżecie, aby możliwości, że ludzie nie chcą.
źródło
[switch]
parametry filtrów.EQV
. Operator, o którym często marzyłem, byłby „i nie”, który promowałby operatora po prawej stronie przed jego zanegowaniem. W ten sposób0xABCD12345678ul ~& 0x00200000u
dałoby 0xABCD12145678ul zamiast 0x12145678ul.Mogę tylko zgadywać, ale powodem może być to, że istnieją obejścia, które są dość proste i czytelne. Rozważmy twój przykład:
Jeśli potrzebujesz wyrażenia, można użyć wbudowanego operatora dostępnego w większości języków (często nazywanego operatorem potrójnym). Oczywiście nie jest to tak eleganckie
A --> B
, ale liczba przypadków użycia może nie uzasadniać dodania (i utrzymania!) Innego operatora:źródło
if
stwierdzenie jest o wiele wyraźniejsze dla wszystkich.Eiffel ma znaczenie
W rzeczywistości ma jeszcze więcej. Ma wiele pół-ścisłych operatorów, a także ścisłych.
Programiści nie używają takich rzeczy, ponieważ nigdy nie są szkoleni, aby dokładnie wiedzieć, czym są, jak z nich korzystać i kiedy ich używać - a także jak projektować z nimi. Ponieważ nigdy nie są szkoleni, nigdy nie proszą o to pisarzy kompilatorów, dlatego ludzie kompilatorów nie zawracają sobie głowy umieszczaniem takich mechanizmów w kompilatorze. Kiedy studenci informatyki i programiści cieni zaczną zdobywać bardziej zaokrąglone wykształcenie, kompilatory zaczną nadrabiać zaległości.
Okazuje się, że kiedy masz język z takimi operatorami boolowskimi i wiesz, jak z nimi projektować i korzystać z nich, wtedy ich używasz.
W Eiffelu użycie słowa kluczowego „implikuje” jest dość widoczne ze względu na projektowanie według umowy ze względu na boolowską naturę twierdzeń o umowie. Istnieje kilka umów, które można poprawnie i skutecznie napisać tylko z operatorem „implikującym”. To pociąga za sobą komentarz, że języki bez umów są dalej bez powodu, aby patrzeć, szkolić i wdrażać stosowanie implikacji.
Dodaj do tego, że większość programistów jest „słaba z matematyki i logiki”, opowiada nam resztę historii. Nawet jeśli w swoim wykształceniu masz duże matematykę i logikę, kiedy wybierzesz język, który nie implementuje konstrukcji takich jak implikacja, wówczas myślisz, że takie rzeczy są niepotrzebne lub nieprzydatne. Rzadko kwestionuje się język i przechodzi do echa: „Cóż, kompilatorzy nie widzą potrzeby” i „Cóż, programiści nie widzą potrzeby” - niekończące się i błędne koło.
Zamiast tego ludzie kompilatora muszą wykonać kopię zapasową teorii, napisać notację językową sugerowaną lub sugerowaną przez teorię (np. Teorię obiektową), niezależnie od tego, o czym myślą lub proszą niemyte masy programistów. Stamtąd profesorowie, nauczyciele i inni specjaliści muszą fachowo szkolić młode papugi w oparciu o surową teorię, a NIE „teorię poprzez soczewki językowe”. Kiedy tak się stanie, ludzie nagle się obudzą i uświadomią sobie, czego im brakowało i co zostało im narzucone.
W tej chwili - jest tyle teorii, które podszywają się pod obiektowe, ale to tylko OO-przez-szklankę-ciemno-z-[wybierz swój język]. Nie można przeczytać większości „teorii” książek na temat OO, ponieważ chcą interpretować teorię przez pryzmat jakiegoś języka. Całkowicie fałszywe i niepoprawne. To byłoby jak nauczanie matematyki opartej na moim kalkulatorze lub mojej reguły slajdów. NIE - człowiek pozwala rzeczywistości uczyć się o sobie, a następnie używa notacji do opisania tego, co obserwuje - nazywa się to „nauką”. Ten inny zacier o nazwie X oparty na języku OO jest tak wypaczony, że ledwo reprezentuje rzeczywistość.
Więc odejdź od języka, spójrz na surową teorię i zacznij od nowa. Nie pozwól, aby ograniczenia, ograniczenia i malowanie w języku mówiły ci o teorii. Po prostu pozwól, aby rzeczywistość teorii podyktowała swój własny zapis, a następnie stamtąd przejdź do sformułowania języka.
Od tego momentu zaczniesz rozumieć, w jaki sposób implikacja i „implikacja” jest nie tylko przydatna, ale także elegancka i bardzo fajna!
Miłego!
źródło
Python ma operator implikacji w sposób ukryty.
Operator mniejszy lub równy jest przeciążony, aby zaakceptować wartości logiczne. W rezultacie można go używać jako operatora implikacji.
Dowód według przykładu (kod Python):
Przypomnijmy, że tabela prawdy operatora implikacji to:
źródło
f() implies g()
nie powinno oceniać,g()
czyf()
jestFalse
, ale<=
oceniag()
w tym przypadku.did_all_possible_stuff = x.do_required_stuff() and (x.supports_optional_stuff() <= x.do_optional_stuff())
zadziała.Eiffel ma operatora „implikującego” i jest bardzo przyjemny w pisaniu warunków wstępnych i dodatkowych. Sprawia, że kod jest bardziej czytelny, niestety to nigdy nie było podstawową intencją języka podobnego do C i zbyt mało osób używało Eiffla, więc piękno „sugeruje”, ponieważ operator nie jest dobrze znany.
źródło
Dla mnie duży problem z implikacjami pojawia się, gdy warunek początkowy jest fałszywy; na przykład: „Jeśli słońce jest zielone, jestem nietoperzem owocowym”. Prawdziwe!
W logice formalnej po prostu działa przypisanie wartości „True” do wartości, gdy warunek implikacji nie jest spełniony. Ale w programowaniu może to prowadzić do sprzecznych z intuicją i zaskakujących wyników.
Wydaje mi się, że przykład podany powyżej przez Heinzi:
Jest znacznie łatwiejszy do zrozumienia i mniej podatny na błędy z powodu niezrozumienia logiki.
W kontekście testowania po prostu zatrzymałbym się, gdy moje założenia stały się fałszywe:
Tak więc, do rzeczy @Eric Lippert, jako programista nie wiem, kiedy użyłbym domyślnego operatora. Zachowanie „False is True” wydaje się przydatne w kontekście matematycznej, formalnej logiki, ale może prowadzić do nieoczekiwanych rezultatów w logice programu.
...
Nikt nie wspominał o zwykłym „?” operator, gdzie „A? B: prawda” jest tym samym, co „implikuje”. Ale podczas gdy logika formalna przypisuje prawdę warunkowi „else”, „?” pozwala programistom przypisać to wprost.
W logice formalnej sprawdza się użycie „true”, ale w programowaniu, jeśli warunek jest fałszywy, wówczas lepsza odpowiedź jest bardziej jak „null” lub „void” lub „skip”, a może nawet false.
Myślę, że ktoś musiałby uzasadnić, dlaczego „implikuje” jest bardziej użytecznym operatorem niż „?”, Instrukcje „jeśli” lub zwykły przepływ programu.
źródło
Rakieta ma
implies
. Makro rozwija się doif
wyrażenia.źródło