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

59

Potrebbe essere una domanda strana, ma perché non vi è alcuna implicazione come operatore logico in molti linguaggi (Java, C, C ++, Python Haskell - sebbene l'ultimo abbia operatori definiti dall'utente è banale per aggiungerlo)? Trovo molto più chiara l'implicazione logica da scrivere (in particolare nelle espressioni assert o asser-like) quindi la 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
}
    
posta Maciej Piechotka 18.01.2013 - 13:48
fonte

9 risposte

61

Potrebbe essere utile avere a volte, senza dubbio. Diversi punti argomentano contro un simile operatore:

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

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

    
risposta data 18.01.2013 - 14:00
fonte
54

Credo che la risposta sia nelle le 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 da An Investigation of the Laws of Thought (1854) di George Boole

:

All the operations of Language, as an instrument of reasoning, may be conducted by a system of signs composed of the following elements, viz.:

1st. Literal symbols, as x, y, &c., representing things as subjects of our conceptions.

2nd. Signs of operation, as +, −, ×, standing for those operations of the mind by which the conceptions of things are combined or resolved so as to form new conceptions involving the same elements.

3rd. The sign of identity, =.

And these symbols of Logic are in their use subject to definite laws, partly agreeing with and partly differing from the laws of the corresponding symbols in the science of Algebra.

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

    
risposta data 18.01.2013 - 15:03
fonte
37

AGGIORNAMENTO: questa domanda era l'argomento del mio blog nel novembre 2015 . Grazie per la domanda interessante!

Visual Basic 6 (e VBScript) disponevano di Imp e Eqv operatori. Nessuno li ha usati. Entrambi sono stati rimossi in VB.NET; a mia conoscenza, nessuno si è lamentato.

Ho lavorato al team di compilatori di Visual Basic (come stagista) per un anno intero e non ho mai notato che VB aveva ancora quegli operatori. Se non fossi stato il ragazzo a scrivere il compilatore VBScript, e quindi ho dovuto testare le loro implementazioni, probabilmente non li avrei notati. Se il ragazzo del team del compilatore non conosce la funzione e non la usa, questo ti dice qualcosa sulla popolarità e l'utilità della funzione.

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

Le funzionalità esistenti e inutilizzate in una lingua e mai richieste in un'altra sono candidati improbabili per introdurle nei moderni linguaggi di programmazione. Soprattutto quando non ci sono abbastanza tempo, sforzi e denaro disponibili nel budget per creare funzionalità che le fanno vogliono

.

    
risposta data 20.01.2013 - 01:12
fonte
19

Posso solo indovinare, 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 hai bisogno di un'espressione, puoi utilizzare l'operatore inline-if disponibile nella maggior parte delle lingue (spesso chiamato operatore ternario). Certo, questo non è 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);
    
risposta data 18.01.2013 - 13:57
fonte
11

Eiffel ha implicazione

In realtà ne ha ancora di più. Ha un numero di operatori semi-severi e 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 - e come progettarli con loro. Poiché non sono mai addestrati, non lo chiedono mai agli scrittori del compilatore, motivo per cui i compilatori 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, li usi.

In Eiffel l'uso della parola chiave "implica" è piuttosto evidente a causa della progettazione per contratto a causa della natura booleana delle asserzioni del contratto. Ci sono alcuni contratti che possono essere scritti solo correttamente ed efficientemente con l'operatore "implica". Questo quindi chiede il commento che le lingue senza contratti sono ulteriormente senza motivo di guardare, addestrare e implementare l'uso delle implicazioni.

Aggiungete a ciò che molti programmatori sono "matematici e deboli di logica" ci dice il resto della storia. Anche se nella tua educazione sei pesante in matematica e logica, quando si sceglie un linguaggio che non implementa costrutti come l'implicazione, allora si tende a pensare che tali cose siano inutili o non utili. Raramente si interroga il linguaggio e si entra in un'eco-camera di: "Beh, i compilatori non vedono il bisogno" e "Beh, i programmatori non vedono il bisogno" - circolo infinito e vizioso.

Invece, le persone del compilatore devono eseguire il backup della teoria, scrivere una notazione linguistica suggerita o implicita dalla teoria (ad esempio la Teoria orientata agli oggetti) indipendentemente da ciò che le masse non lavate dei programmatori pensano o chiedono. Da lì, professori, insegnanti e altri professionisti hanno bisogno di addestrare sapientemente giovani menti di mente basate sulla teoria grezza e NON "teoria attraverso la lente del linguaggio". Quando ciò accade, le persone improvvisamente si svegliano e si rendono conto di ciò che sono scomparsi e di ciò che è stato loro imposto.

In questo momento - c'è tanta teoria là fuori che si maschera come Object Oriented, ma è semplicemente O-O-through-a-glass-darkly-of- [pick-your-language]. Non si possono leggere molti libri di "teoria" su O-O perché vogliono interpretare ciò che la teoria è attraverso l'obiettivo di un linguaggio. Totalmente falso e scorretto. Sarebbe come insegnare la matematica sulla mia calcolatrice o la mia regola di slide. Nessuno consente alla realtà di insegnare a se stessa e quindi usa una notazione per descrivere ciò che si osserva - si chiama "scienza". Questo altro mash chiamato O-O-based-on-language-X è così distorto da rappresentare a malapena la realtà.

Quindi, allontanati dal linguaggio, dai un'occhiata alla teoria grezza e ricomincia. Non lasciare che limiti, vincoli e lavori di verniciatura di una lingua ti dica quale sia la teoria. Semplicemente lascia che la realtà della teoria imponga la propria notazione e poi si trasferisca da lì nella formulazione di un linguaggio.

Da lì inizierai a capire come le implicazioni e le "implicazioni" non solo siano utili, ma eleganti e molto interessanti!

Ne hai uno fantastico!

    
risposta data 13.05.2014 - 03:28
fonte
7

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

L'operatore meno-o-uguale è sovraccaricato per accettare valori booleani. Di conseguenza, è possibile utilizzarlo come operatore implicito.

Prova ad 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.

Richiama la tabella di verità dell'operatore di implicazione è:

LEFT RIGHT RESULT
F    F     T
F    T     T
T    F     F
T    T     T
    
risposta data 15.07.2014 - 10:21
fonte
5

Eiffel ha un operatore "implica" ed è molto utile per scrivere pre e post-condizioni. Rende il codice più leggibile, sfortunatamente non è mai stato un intension fondamentale per il linguaggio C e troppe poche persone hanno usato eiffel per cui la bellezza di "implica" come operatore non è ben nota.

    
risposta data 06.11.2013 - 09:45
fonte
2

Per me, il grosso problema con gli implied arriva quando 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 dia sopra:

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

È molto più facile da capire e meno incline agli errori a causa di incomprensione della logica.

Nel contesto dei test, avrei fermato il momento in cui le mie supposizioni diventavano false:

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

Quindi, per il punto di @Eric Lippert, come programmatore non so quando userò un operatore implicito. Il comportamento "False is True" sembra utile nel contesto della logica formale e matematica, ma potrebbe portare a risultati inattesi 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 "altro", "?" lascia che lo sviluppatore assegni esplicitamente.

In logica formale, l'uso di "true" funziona, ma in programmazione, se la condizione è falsa, la risposta migliore è più "null" o "void" o "skip", o anche forse false.

Penso che qualcuno dovrebbe spiegare perché "implica" è un operatore più utile di "?", o "se" dichiarazioni, o solo regolare flusso di programma.

    
risposta data 01.05.2014 - 16:45
fonte
1

Racket ha implies . Espande la macro in un'espressione if .

    
risposta data 02.05.2014 - 17:11
fonte

Leggi altre domande sui tag