Perché le lingue non includono l'implicazione come operatore logico?


60

Potrebbe essere una domanda strana, ma perché non ci sono implicazioni come operatore logico in molti linguaggi (Java, C, C ++, Python Haskell - anche se come ultimo hanno operatori definiti dall'utente è banale aggiungerlo)? Trovo che le implicazioni logiche siano molto più chiare da scrivere (in particolare in affermazioni o espressioni assertive), quindi negazione con o:

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
Perché non è stato messo in C; se fosse stato messo allora C ++, Java e C # lo avrebbero avuto.
m3th0dman,

4
Ma C non ce l'ha, a sua volta, perché non è una parte comune del linguaggio assembly. Considerando che come tutti i set di istruzioni che conosco includono e, o no, non ne conosco nessuno che implica implica - senza dubbio qualcuno verrà a parlarmi di un set di istruzioni oscuro che farà presto ...
Jack Aidley,

4
Forse è stato considerato ridondante perché (1) è meno primitivo di "^", "v", "~", (2) risparmia pochissimo digitando poiché "A => B" equivale a "~ A v B" .
Giorgio,

4
Le lingue che si occupano di costruzioni logiche hanno maggiori probabilità di averlo. Principalmente tra questi c'è il prologo

9
Sono sorpreso che pensi che il assertn. 1 sia più chiaro del n. 2. Ho fissato il numero 1 per un po 'di tempo e ancora non riesco a vedere come il suo comportamento possa essere considerato intuitivo. (Soprattutto con l'ulteriore !=capovolgere la logica)
Chris Burt-Brown,

Risposte:


61

Potrebbe essere utile a volte, senza dubbio. Diversi punti discutono contro un tale operatore:

  • I personaggi -e >sono preziosi, sia in isolamento che combinati. Molte lingue li usano già per indicare altre cose. (E molti non possono usare i set di caratteri unicode per la loro sintassi.)
  • L'implicazione è molto controintuitiva, anche per le persone logiche come i programmatori. Il fatto che tre delle quattro voci della tabella della verità siano truesorprese per molte persone.
  • Tutti gli altri operatori logici sono simmetrici, il che farebbe ->un'eccezione all'ortogonalità.
  • Allo stesso tempo, c'è una soluzione semplice: usare operatori !e ||.
  • L'implicazione è ampiamente usata meno spesso di logica and/ or.

Questo è probabilmente il motivo per cui l'operatore è raro oggi. Certamente potrebbe diventare più comune, poiché i nuovi linguaggi dinamici usano Unicode per tutto e il sovraccarico dell'operatore diventa di nuovo più alla moda.


22
Il tuo primo punto discute solo sull'uso di '->' come simbolo per l'operatore, non sul fatto di avere effettivamente l'operatore. Gli altri sono buoni punti.
AShelly,

14
"Allo stesso tempo, c'è una soluzione semplice: usare! E &&.": In effetti, il modo più semplice di simulare "->" (o "=>", come è più comune in matematica), è usare !e ||, non !e &&: A -> Bè equivalente a !A || Bcui è equivalente !(A && !B).
Giorgio,

22
"Il fatto che tre delle quattro voci della tabella di verità siano vere sorprese molte persone." Wat. Conosco un altro operatore con la stessa funzione che viene usata piuttosto spesso ...
l0b0

9
@ l0b0, sono un programmatore che ha studiato CS, ma è stato tanto tempo fa. Avevo dimenticato che "implica" è un'operazione formale con due operandi che restituisce un valore di verità, quindi all'inizio ero confuso dalla natura di questa domanda. Nel linguaggio quotidiano uso sempre "implica" quando il primo operando è già noto per essere vero ("X è vero, quindi Y deve essere vero"). Dopo un minuto, mi sono ricordato di come funziona "implica" formale, ma il fatto rimane - anche per qualcuno che una volta ha studiato la logica formale, l'intento non mi era chiaro. E se non l'avessi mai studiato, alla fine non avrebbe nemmeno avuto senso.
Ben Lee,

5
(a) In C -> è usato come operatore. Nessuno se ne lamenta. Vorrei usare => comunque. (b) Controintuitivo per chi? La definizione di implicazione è proprio questa, una definizione. (c) la sottrazione non è commutativa. Nessuno se ne lamenta. (d) Penso che intendi! e || A causa della precedenza (e) sono spesso necessari anche. Lo stesso argomento potrebbe essere usato contro && o ||; Fai la tua scelta. (e) Forse è perché non è nella maggior parte delle lingue. Molti usi di || potrebbe essere concisamente e (almeno per me) intuitivamente sostituito da implicazioni.
Theodore Norvell,

54

Credo che la risposta risieda nelle basi matematiche . L'implicazione è generalmente considerata e definita come un'operazione derivata, non elementare, di algebre booleane. I linguaggi di programmazione seguono questa convenzione.

Questa è la proposizione I del capitolo II di An Investigation of the Laws of Thought (1854) di George Boole :

Tutte le operazioni del linguaggio, come strumento di ragionamento, possono essere condotte da un sistema di segni composto dai seguenti elementi, vale a dire:

1 °. Simboli letterali, come x, y, ecc., Che rappresentano le cose come soggetti delle nostre concezioni.

2 °. Segni di operazione, come +, -, ×, rappresentano le operazioni della mente mediante le quali le concezioni delle cose vengono combinate o risolte in modo da formare nuove concezioni che coinvolgono gli stessi elementi.

3 °. Il segno di identità, =.

E questi simboli della Logica sono nel loro uso soggetti a leggi definite, in parte in accordo e in parte diverse dalle leggi dei simboli corrispondenti nella scienza dell'Algebra.

Il segno + di Boole rappresenta la stessa "operazione della mente" che oggi riconosciamo sia come "booleano" che come unione di insiemi. Allo stesso modo i segni - e × corrispondono alla nostra negazione booleana, complemento di un insieme, "booleano" e "intersezione di insiemi.


+1 - risposta solida. Algebra booleana e le semplificazioni logiche che consente di guidare molta metodologia di programmazione. L'uso di un "implica ..." potrebbe potenzialmente interferire con le condizioni "non importa".

3
1. Dipende dalla definizione. È possibile definire o come a || b = !(!a && !b)(ho incontrato o come operatore derivato in logica). 2. Il motivo per cui viene fatto è di solito per semplificare l'induzione dimostra che credo (sappiamo che gli operatori derivati ​​sono solo scorciatoie, quindi non abbiamo bisogno di un caso separato per loro). @ GlenH7: quali condizioni "non importa"? a --> bè lo stesso di !a || b.
Maciej Piechotka,

3
Inoltre - abbiamo altri operatori derivati ​​come xor ( !=) nxor ( ==) ...
Maciej Piechotka,

5
In realtà, puoi derivare tutto da NAND !(a && b)o NOR !(a || b). Ad esempio, NOT a == a NAND a, a AND b == NOT(a NAND b), a OR b == (NOT a) NAND (NOT b). Ma fornire solo un operatore NAND ti mette nel regno delle lingue esoteriche (che si adatta sorprendentemente bene, dato il nome utente del risponditore ;-)).
Stefan Majewsky,

1
@Stefan: puoi anche derivare tutto da un IMPL.
Mason Wheeler,

37

AGGIORNAMENTO: Questa domanda è stata l'oggetto del mio blog a novembre 2015 . Grazie per l'interessante domanda!


Visual Basic 6 (e VBScript) aveva Impe Eqvoperatori. Nessuno li ha usati. Entrambi sono stati rimossi in VB.NET; per quanto ne so, nessuno si è lamentato.

Ho lavorato nel team di compilatore di Visual Basic (come stagista) per un anno intero e non ho mai notato che VB avesse anche quegli operatori. Se non fossi stato il tipo a scrivere il compilatore VBScript e quindi avessi dovuto testare le loro implementazioni, probabilmente non me ne sarei accorto. Se il ragazzo del team del compilatore non è a conoscenza della funzione e non la utilizza, questo ti dice qualcosa sulla popolarità e l'utilità della funzione.

Hai citato lingue simili a C. Non posso parlare con C o C ++ o Java ma posso parlare con C #. C'è un elenco di funzionalità suggerite dall'utente per C # letteralmente più lunghe del braccio. Per quanto ne sappia, nessun utente ha mai proposto un simile operatore al team C # e ho esaminato l'elenco molte, molte volte.

Funzionalità esistenti e non utilizzate in una lingua e mai richieste in un'altra sono candidati improbabili a trasformarlo in moderni linguaggi di programmazione. Soprattutto quando non c'è abbastanza tempo e fatica e denaro a disposizione nel bilancio per rendere le caratteristiche che le persone non vogliono.


IMP risale come operatore ai giorni GWBASIC. Lo ricordo dal 1979.
zarchasmpgmr

1
Ho letto che IMPL è molto utile per i contratti di codice. (Che VB non aveva.)
Mason Wheeler

3
I programmatori VBScript erano probabilmente il gruppo meno propenso a utilizzare un tale operatore. In questo momento desidero che PowerShell avesse un operatore implicito in modo da poter implementare in modo più semplice e leggibile alcuni [switch]parametri del filtro.
brianary

Ricordo IMP da DEC BASIC. Non ricordo EQV. L'operatore che ho spesso desiderato sarebbe "e non", il che promuoverà l'operatore di destra prima di negarlo. Pertanto, 0xABCD12345678ul ~& 0x00200000urestituirebbe 0xABCD12145678ul anziché 0x12145678ul.
supercat

19

Posso solo immaginare, ma una ragione potrebbe essere che ci sono soluzioni alternative che sono abbastanza semplici e leggibili. Consideriamo il tuo esempio:

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

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

Se è necessaria un'espressione, è possibile utilizzare l'operatore inline-if disponibile nella maggior parte delle lingue (spesso chiamato operatore ternario). Certo, questo non è così elegante come A --> B, ma il numero di casi d'uso potrebbe non giustificare l'aggiunta (e la manutenzione!) Di un altro operatore:

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

2
A partire da asserzioni - c'è una buona ragione. Il primo produrrà (in molte implementazioni) il messaggio "errore asserzione: iv! = Null" mentre il secondo "errore asserzione: mode! = ECB -> iv! = Null".
Maciej Piechotka,

2
+1, stavo per porre la stessa cosa alla domanda (dal momento che non ho molta familiarità con le "implicazioni", non si presenta mai di giorno in giorno). L' ifaffermazione è molto, molto più chiara per quasi tutti.
Izkata,

12

Eiffel ha implicazioni

In realtà ha ancora di più. Ha un numero di operatori semi-severi oltre che severi.

Il motivo per cui i programmatori non usano queste cose è perché non sono mai addestrati a sapere esattamente cosa sono, come usarli e quando usarli, oltre a come progettare con loro. Poiché non sono mai addestrati, non lo chiedono mai agli autori del compilatore, motivo per cui le persone del compilatore non si preoccupano di inserire tali meccanismi nel compilatore. Quando gli studenti di informatica e i programmatori di Shade Tree iniziano a ricevere un'istruzione più completa, i compilatori inizieranno a recuperare.

Si scopre che una volta che hai una lingua con tali operatori booleani e sai come progettare con loro e usarli, allora li usi.

In Eiffel l'uso della parola chiave "implica" è piuttosto importante a causa della progettazione per contratto a causa della natura booleana delle asserzioni contrattuali. Esistono alcuni contratti che possono essere scritti in modo corretto ed efficiente solo con l'operatore "implica". Ciò fa quindi supporre che le lingue senza contratto siano ulteriormente prive di motivo per esaminare, formare e implementare l'uso dell'implicazione.

Aggiungete a ciò che la maggior parte dei programmatori sono "deboli in matematica e logica" e ci racconta il resto della storia. Anche se sei matematico e logico nella tua educazione, quando si sceglie una lingua che non implementa costrutti come implicazioni, si tende a pensare che tali cose siano inutili o non utili. Raramente si mette in discussione il linguaggio e si entra in una camera di eco di: "Beh, i ragazzi del compilatore non vedono il bisogno" e "Beh, i programmatori non vedono il bisogno" - cerchio infinito e vizioso.

Invece, le persone del compilatore devono fare il backup della teoria, scrivere una notazione linguistica che è suggerita o implicita dalla teoria (ad esempio teoria orientata agli oggetti) indipendentemente da ciò che le masse non programmate di programmatori pensano o chiedono. Da lì, professori, insegnanti e altri professionisti hanno bisogno di addestrare sapientemente giovani menti pazze basate sulla teoria grezza e NON sulla "teoria attraverso la lente del linguaggio". Quando ciò accade, le persone si sveglieranno improvvisamente e realizzeranno ciò che si sono persi e ciò che è stato soffocato su di loro.

In questo momento - c'è così tanta teoria là fuori che si maschera da Object Oriented, ma è solo OO-through-a-glass-darkly-of- [scegli il tuo linguaggio]. Non si può leggere la maggior parte dei libri di "teoria" su OO perché vogliono interpretare ciò che la teoria è attraverso l'obiettivo di un certo linguaggio. Totalmente falso e errato. Sarebbe come insegnare la matematica sulla mia calcolatrice o la mia regola di scorrimento. NO - uno permette alla realtà di insegnare a se stesso e quindi usa una notazione per descrivere ciò che si osserva - che si chiama "scienza". Quest'altro mash chiamato OO-based-on-language-X è così distorto da rappresentare a malapena la realtà.

Quindi, allontanati dalla lingua, dai un'occhiata alla teoria grezza e ricomincia. Non lasciare che limitazioni, vincoli e lavori di pittura di una lingua ti dicano qual è la teoria. Lascia semplicemente che la realtà della teoria imponga la propria notazione e poi passa da lì alla formulazione di una lingua.

Da lì, inizierai a capire come l'implicazione e "implica" non sia solo utile, ma elegante e molto interessante!

Buona giornata!


7

Python ha un operatore di implicazioni in una sorta di modo nascosto.

L'operatore inferiore o uguale a è sovraccarico per accettare valori booleani. Di conseguenza, è possibile utilizzarlo come operatore di implicazione.

Prova di esempio (codice 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.

Ricordare che la tabella di verità dell'operatore di implicazione è:

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

2
Questo è fantastico, ma purtroppo ha le proprietà di rigidità sbagliate: f() implies g()non dovrebbe valutare g()se lo f()è False, ma <=valuta g()in questo caso.
Jon Purdy,

2
@Jon Purdy - A rigor di termini, la valutazione del corto circuito è una funzione opzionale degli operatori binari. Quindi tecnicamente, questa è un'implementazione perfettamente legittima dell'operatore implicativo. Detto questo, dubito davvero che Guido van Rossum intendesse addirittura che fosse un operatore di implicazioni. Questa è solo una stranezza di paragoni booleani.
Mackenzie

Certo, stavo dicendo che è un'osservazione interessante, ma non qualcosa che dovresti usare nei programmi reali perché non è un corto circuito e questo potrebbe sorprendere qualcuno se si aspettasse did_all_possible_stuff = x.do_required_stuff() and (x.supports_optional_stuff() <= x.do_optional_stuff())che funzionasse.
Jon Purdy,

2
Funziona anche in C e C ++.
Ben Voigt,

5

Eiffel ha un operatore "implicito" ed è molto bello per scrivere pre e post-condizioni. Rende il codice più leggibile, sfortunatamente non è mai stata un'intenzione fondamentale per il linguaggio C e troppe persone hanno usato eiffel, quindi la bellezza di "implica" come operatore non è ben nota.


2

Per me, il grosso problema con implica implica che la condizione iniziale è falsa; per esempio: "Se il sole è verde, allora sono un pipistrello della frutta". Vero!

Nella logica formale funziona semplicemente per assegnare "True" al valore quando la condizione dell'implicazione non è soddisfatta. Ma nella programmazione, ciò potrebbe portare a risultati contro-intuitivi e sorprendenti.

In realtà penso che l'esempio @Heinzi fornisca sopra:

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

È molto più facile da capire e meno soggetto a errori dovuti a malintesi sulla logica.

Nel contesto del test, fermerei il momento in cui le mie assunzioni sono diventate false:

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

Quindi, al punto di @Eric Lippert, come programmatore non so quando userei un operatore implicito. Il comportamento "False is True" sembra utile nel contesto della logica matematica e formale, ma potrebbe portare a risultati inaspettati nella logica del programma.

...

Nessuno ha menzionato il "?" Comune operatore, dove "A? B: true" è uguale a "implica". Ma mentre la logica formale assegna true alla condizione "else", "?" consente allo sviluppatore di assegnarlo esplicitamente.

Nella logica formale, l'utilizzo di "true" funziona, ma in programmazione, se la condizione è falsa, la risposta migliore è più simile a "null" o "void" o "skip", o forse falso.

Penso che qualcuno dovrebbe spiegare il motivo per cui "implica" è un operatore più utile delle istruzioni "?", O "if", o semplicemente un normale flusso di programma.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.