Perché la maggior parte delle lingue tradizionali non supporta la sintassi "x <y <z" per i confronti booleani a 3 vie?


34

Se voglio confrontare due numeri (o altre entità ben ordinate), lo farei con x < y. Se voglio confrontarne tre, lo studente di algebra delle superiori suggerirà di provare x < y < z. Il programmatore in me risponderà quindi con "no, non è valido, devi farlo x < y && y < z".

La maggior parte delle lingue che ho incontrato non sembra supportare questa sintassi, il che è strano dato quanto sia comune in matematica. Python è un'eccezione notevole. JavaScript sembra un'eccezione, ma in realtà è solo uno sfortunato sottoprodotto della precedenza dell'operatore e delle conversioni implicite; in node.js, 1 < 3 < 2valuta true, perché è davvero (1 < 3) < 2 === true < 2 === 1 < 2.

Quindi, la mia domanda è questa: perché x < y < znon è comunemente disponibile nei linguaggi di programmazione, con la semantica prevista?


1
Ecco il file grammaticale, che si inseriscono facilmente nella documentazione di Python - Non credo sia così difficile: docs.python.org/reference/grammar.html
Aaron Hall

Non conosco altre lingue e conosco Python, ma posso parlare della semplicità dell'interpretazione di Python. Forse dovrei rispondere. Ma non sono d'accordo con la conclusione di gnasher729 sul fatto che stia danneggiando.
Aaron Hall,

@ErikEidt - La richiesta è quella di poter scrivere espressioni matematiche come ci hanno insegnato al liceo (o prima). Chiunque sia matematicamente incline sa cosa significa $ a <b <c <d $. Solo perché esiste una funzione non significa che devi usarla. A chi non piace può sempre fare una regola personale o di progetto vietandone l'uso.
David Hammen,

2
Penso che ciò che ne consegue è che è meglio per il team C # (ad esempio) esplorare LINQ e in futuro forse registrare tipi e pattern matching rispetto ad aggiungere un po 'di zucchero sintattico che salverebbe le persone 4 sequenze di tasti e non proprio aggiungi espressività (puoi anche scrivere helpermethods come static bool IsInRange<T>(this T candidate, T lower, T upper) where T : IComparable<T>se ti disturbasse davvero a vedere &&s)
sara,

1
SQL è piuttosto "mainstream" e puoi scrivere "x tra 1 e 10"
JoelFan

Risposte:


30

Si tratta di operatori binari che, se concatenati, producono normalmente e naturalmente un albero di sintassi astratto come:

albero di sintassi astratto normale per operatori binari

Quando valutato (cosa che si fa dalle foglie), questo produce un risultato booleano da x < y, quindi si ottiene un errore di tipo nel tentativo di fare boolean < z. Per x < y < zfunzionare come hai discusso, devi creare un caso speciale nel compilatore per produrre un albero di sintassi come:

albero di sintassi per casi speciali

Non che non sia possibile farlo. Lo è ovviamente, ma aggiunge una certa complessità al parser per un caso che non si presenta così spesso. Stai fondamentalmente creando un simbolo che a volte si comporta come un operatore binario e talvolta si comporta efficacemente come un operatore ternario, con tutte le implicazioni della gestione degli errori e tale che comporta. Ciò aggiunge molto spazio perché le cose vadano male che i progettisti linguistici preferirebbero evitare, se possibile.


1
"quindi viene visualizzato un errore di tipo durante il tentativo di eseguire booleano <z", non se il compilatore consente il concatenamento valutando y sul posto per il confronto z. "Ciò aggiunge molto spazio perché le cose vadano male che i progettisti linguistici preferirebbero evitare, se possibile". In realtà, Python non ha problemi a farlo e la logica per l'analisi è limitata a una singola funzione: hg.python.org/cpython/file/tip/Python/ast.c#l1122 - non c'è molto spazio per le cose da fare sbagliato. "a volte si comporta come un operatore binario e talvolta si comporta effettivamente come un operatore trinario", in Python, l'intera catena di confronto è ternaria.
Aaron Hall,

2
Non ho mai detto che non fosse fattibile, solo un lavoro extra con una complessità extra. Altre lingue non devono scrivere alcun codice separato solo per gestire i loro operatori di confronto. Lo ottieni gratuitamente con altri operatori binari. Devi solo specificare la loro precedenza.
Karl Bielefeldt,

Sì, ma ... c'è già un operatore ternario disponibile in molte lingue?
JensG,

1
@JensG La denotazione di ternario significa che ci vogliono 3 argomenti. Nel contesto del tuo link, è un operatore di condizione ternaria. Apparentemente "trinario" in un termine coniato per un operatore che sembra prendere 2 ma effettivamente prende 3. Il mio problema principale con questa risposta è che è principalmente FUD.
Aaron Hall,

2
Sono uno dei downvot su questa risposta accettata. (@JesseTG:. Si prega di unaccept questa risposta) Questa domanda confonde ciò che x<y<zsignifica, o più importante, x<y<=z. Questa risposta interpreta x<y<zcome un operatore trinario. Questo è esattamente il modo in cui questa espressione matematica ben definita non dovrebbe essere interpretata. x<y<zè invece una scorciatoia per (x<y)&&(y<z). I singoli confronti sono ancora binari.
David Hammen,

37

Perché x < y < znon è comunemente disponibile nei linguaggi di programmazione?

In questa risposta lo concludo

  • sebbene questo costrutto sia banale da implementare nella grammatica di una lingua e crei valore per gli utenti della lingua,
  • i motivi principali per cui ciò non esiste nella maggior parte delle lingue è dovuto alla sua importanza rispetto ad altre caratteristiche e alla riluttanza degli organi di governo delle lingue a
    • sconvolgere gli utenti con modifiche potenzialmente violenti
    • per passare all'attuazione della funzione (es. pigrizia).

introduzione

Posso parlare dal punto di vista di un pitonista su questa domanda. Sono un utente di una lingua con questa funzione e mi piace studiare i dettagli di implementazione della lingua. Oltre a ciò, ho una certa familiarità con il processo di modifica di linguaggi come C e C ++ (lo standard ISO è governato da un comitato e aggiornato per anno) e ho visto sia Ruby che Python implementare le ultime modifiche.

Documentazione e implementazione di Python

Dalla documentazione / grammatica, vediamo che possiamo unire qualsiasi numero di espressioni con operatori di confronto:

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "!="
                   | "is" ["not"] | ["not"] "in"

e la documentazione afferma inoltre:

I confronti possono essere concatenati in modo arbitrario, ad es. X <y <= z è equivalente a x <y e y <= z, tranne per il fatto che y viene valutato solo una volta (ma in entrambi i casi z non viene valutato affatto quando viene trovato x <y essere falso).

Equivalenza logica

Così

result = (x < y <= z)

è logicamente equivalente in termini di valutazione di x, ye z, con l'eccezione che yviene valutata per due volte:

x_lessthan_y = (x < y)
if x_lessthan_y:       # z is evaluated contingent on x < y being True
    y_lessthan_z = (y <= z)
    result = y_lessthan_z
else:
    result = x_lessthan_y

Ancora una volta, la differenza è che y viene valutato solo una volta con (x < y <= z).

(Nota, le parentesi sono completamente inutili e ridondanti, ma le ho usate per il beneficio di quelle provenienti da altre lingue e il codice sopra è Python abbastanza legale.)

Ispezione dell'albero di sintassi astratto analizzato

Possiamo esaminare come Python analizza gli operatori di confronto concatenati:

>>> import ast
>>> node_obj = ast.parse('"foo" < "bar" <= "baz"')
>>> ast.dump(node_obj)
"Module(body=[Expr(value=Compare(left=Str(s='foo'), ops=[Lt(), LtE()],
 comparators=[Str(s='bar'), Str(s='baz')]))])"

Quindi possiamo vedere che questo non è davvero difficile da analizzare per Python o qualsiasi altra lingua.

>>> ast.dump(node_obj, annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE()], [Str('bar'), Str('baz')]))])"
>>> ast.dump(ast.parse("'foo' < 'bar' <= 'baz' >= 'quux'"), annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE(), GtE()], [Str('bar'), Str('baz'), Str('quux')]))])"

E contrariamente alla risposta attualmente accettata, l'operazione ternaria è un'operazione di confronto generica, che accetta la prima espressione, un iterabile di confronti specifici e un iterabile di nodi di espressione da valutare se necessario. Semplice.

Conclusione su Python

Personalmente trovo che la semantica della gamma sia piuttosto elegante e la maggior parte dei professionisti di Python che conosco incoraggerebbero l'uso della funzione, invece di considerarla dannosa: la semantica è chiaramente indicata nella documentazione ben nota (come notato sopra).

Si noti che il codice viene letto molto più di quanto sia scritto. I cambiamenti che migliorano la leggibilità del codice dovrebbero essere abbracciati, non scontati sollevando spettri generici di Paura, Incertezza e Dubbio .

Quindi perché x <y <z non è comunemente disponibile nei linguaggi di programmazione?

Penso che ci sia una confluenza di ragioni incentrate sull'importanza relativa della caratteristica e sul relativo momento / inerzia del cambiamento consentito dai governatori delle lingue.

Domande simili possono essere poste su altre funzionalità linguistiche più importanti

Perché l'ereditarietà multipla non è disponibile in Java o C #? Non c'è una buona risposta qui a nessuna delle due domande . Forse gli sviluppatori erano troppo pigri, come sostiene Bob Martin, e le ragioni fornite sono semplicemente delle scuse. E l'ereditarietà multipla è un argomento piuttosto importante nell'informatica. È certamente più importante del concatenamento dell'operatore.

Esistono soluzioni semplici

Il concatenamento dell'operatore di confronto è elegante, ma non altrettanto importante dell'eredità multipla. E proprio come Java e C # hanno interfacce come soluzione alternativa, così fa ogni linguaggio per confronti multipli: è sufficiente concatenare i confronti con "e" s booleani, che funzionano abbastanza facilmente.

La maggior parte delle lingue sono governate dal comitato

La maggior parte delle lingue si sta evolvendo per comitato (piuttosto che avere un sensibile dittatore benevolo per la vita come ha fatto Python). E suppongo che questo problema non abbia visto abbastanza supporto per farcela dai suoi rispettivi comitati.

Le lingue che non offrono questa funzione possono cambiare?

Se una lingua lo consente x < y < zsenza la semantica matematica prevista, questo cambierebbe radicalmente. Se non lo consentisse in primo luogo, sarebbe quasi banale aggiungere.

Rottura dei cambiamenti

Per quanto riguarda le lingue con i cambiamenti di rotta: aggiorniamo le lingue con i cambiamenti del comportamento di rottura - ma gli utenti tendono a non apprezzare questo, in particolare gli utenti di funzionalità che potrebbero essere interrotte. Se un utente fa affidamento sul precedente comportamento di x < y < z, probabilmente protesterebbe ad alta voce. E poiché la maggior parte delle lingue sono governate da una commissione, dubito che otterremmo molta volontà politica per sostenere un simile cambiamento.


Onestamente, mi prendo alcun problema con la semantica forniti da linguaggi che operazioni di confronto catena come `x <y <z` ma è banale per uno sviluppatore di mentalmente mappare x < y < za (x < y) && (y < z). Scegliendo le lendini, il modello mentale per il confronto incatenato è la matematica generale. Il confronto classico non è la matematica in generale, ma la logica booleana. x < yproduce una risposta binaria {0}. y < zproduce una risposta binaria {1}. {0} && {1}produce la risposta descrittiva. La logica è composta, non ingenuamente incatenata.
K. Alan Bates,

Per comunicare meglio, ho preceduto la risposta con una sola frase che riassume direttamente l'intero contenuto. È una frase lunga, quindi l'ho fatta a pezzi.
Aaron Hall,

2
La ragione principale per cui alcune lingue implementano questa funzione è che prima di Guido nessuno ci pensava nemmeno. Le lingue che ereditano da C non possono ottenere questo "giusto" (matematicamente giusto) ora principalmente perché gli sviluppatori di C lo hanno "sbagliato" (matematicamente sbagliato) oltre 40 anni fa. C'è un sacco di codice là fuori che dipende dalla natura controintuitiva di come interpretano quelle lingue x<y<z. Una lingua ha una volta la possibilità di ottenere qualcosa del genere, e quella possibilità è all'inizio della lingua.
David Hammen,

1
@ K.AlanBates Fai 2 punti: 1) il concatenamento dell'operatore è sciatto e 2) lo zucchero sintattico non ha valore. Alla prima: ho dimostrato che il concatenamento dell'operatore è deterministico al 100%, no? Forse alcuni programmatori sono troppo pigri mentalmente per espandere la loro capacità di comprendere il costrutto? Al secondo punto: mi sembra che tu stia litigando direttamente contro la leggibilità? Lo zucchero sintattico di solito non è considerato positivo quando migliora la leggibilità? Se è normale pensare in questo modo, perché un programmatore non vorrebbe comunicare così? Il codice dovrebbe essere scritto per essere letto, no?
Aaron Hall,

2
I have watched both Ruby and Python implement breaking changes.Per coloro che sono curiosi, ecco un cambiamento sostanziale
user2023861

13

I linguaggi dei computer tentano di definire le unità più piccole possibili e consentono di combinarle. L'unità più piccola possibile sarebbe qualcosa come "x <y" che dà un risultato booleano.

Puoi chiedere un operatore ternario. Un esempio potrebbe essere x <y <z. Ora quali combinazioni di operatori consentiamo? Ovviamente dovrebbe essere consentito x> y> z o x> = y> = z oppure x> y> = z o forse x == y == z. Che dire di x <y> z? x! = y! = z? Cosa significa l'ultimo, x! = Y e y! = Z o che tutti e tre sono diversi?

Ora promozioni di argomenti: in C o C ++, gli argomenti verrebbero promossi in un tipo comune. Quindi cosa significa x <y <z significa di x è doppio ma y e z sono long long int? Tutti e tre promossi per raddoppiare? O y è preso come doppio una volta e tanto più a lungo nell'altra volta? Cosa succede se in C ++ uno o entrambi gli operatori sono sovraccarichi?

E infine, permetti un numero qualsiasi di operandi? Come un <b> c <d> e <f> g?

Bene, tutto diventa molto complicato. Ora ciò che non mi dispiacerebbe è che x <y <z produca un errore di sintassi. Perché l'utilità di esso è piccola rispetto al danno arrecato ai principianti che non riescono a capire cosa faccia effettivamente x <y <z.


4
Quindi, in breve, è solo una funzione difficile da progettare bene.
Jon Purdy,

2
Questo non è davvero un motivo per spiegare perché nessun linguaggio ben noto contiene questa funzione. È un dato di fatto, è abbastanza facile includerlo in una lingua in un modo ben definito. Si tratta solo di visualizzarlo come un elenco collegato da operatori di tipo simile invece che ogni operatore è binario. Lo stesso può essere fatto per le somme x + y + z, con l'unica differenza che ciò non implica alcuna differenza semantica. Quindi è solo che nessuna lingua ben nota si è mai preoccupata di farlo.
cmaster

1
Penso che in Python sia un po 'un'ottimizzazione, ( x < y < zessendo equivalente ((x < y) and (y < z))ma yvalutato solo una volta ) che immagino che i linguaggi compilati ottimizzino. "Perché l'utilità di esso è piccola rispetto al danno arrecato ai principianti che non riescono a capire cosa faccia effettivamente x <y <z." Penso che sia incredibilmente utile. Probabilmente -1 per quello ...
Aaron Hall

Se il proprio obiettivo è progettare un linguaggio che elimini tutte le cose che potrebbero essere fonte di confusione per i programmatori più insensati, un tale linguaggio esiste già: COBOL. Preferirei usare Python, me stesso, dove si può davvero scrivere a < b > c < d > e < f > g, con il significato "ovvio" (a < b) and (b > c) and (c < d) and (d > e) and (e < f) and (f > g). Solo perché puoi scrivere ciò non significa che dovresti. L'eliminazione di tali mostruosità è di competenza della revisione del codice. D'altra parte, scrivere 0 < x < 8in python ha l'ovvio (senza virgolette) che significa che x è compreso tra 0 e 8, esclusivo.
David Hammen,

@DavidHammen, ironia della sorte, COBOL in effetti consente un <b <c
JoelFan

10

In molti linguaggi di programmazione, x < yè un'espressione binaria che accetta due operandi e restituisce un singolo risultato booleano. Pertanto, se concatenare più espressioni true < ze false < znon ha senso e se tali espressioni vengono valutate correttamente, è probabile che producano risultati errati.

È molto più facile pensare x < ya una chiamata di funzione che accetta due parametri e produce un singolo risultato booleano. In effetti, ecco quante lingue lo implementano sotto il cofano. È compostabile, facilmente compilabile e funziona.

Lo x < y < zscenario è molto più complicato. Ora il compilatore, in effetti, deve la moda di tre funzioni: x < y, y < z, e il risultato di questi due valori-a-bit insieme, il tutto nel contesto di un dubbio grammaticale linguaggio ambiguo .

Perché l'hanno fatto nell'altro modo? Perché è una grammatica non ambigua, molto più facile da implementare e molto più facile da correggere.


2
Se stai progettando la lingua, hai l'opportunità di renderla il risultato giusto .
JesseTG,

2
Ovviamente risponde alla domanda. Se la domanda è davvero perché , la risposta è "perché è quello che hanno scelto i progettisti del linguaggio". Se riesci a trovare una risposta migliore di quella, cercala. Nota che Gnasher ha sostanzialmente detto la stessa cosa nel primo paragrafo della sua risposta .
Robert Harvey,

3
Ancora una volta, stai dividendo i peli. I programmatori tendono a farlo. "Vuoi portare fuori la spazzatura?" "No." "Tirerai fuori la spazzatura?" "Sì."
Robert Harvey,

2
Contestano anche l'ultimo paragrafo. Python supporta il confronto tra catene e il suo parser è LL (1). Non è necessariamente difficile da definire e attuare la semantica sia: Python dice solo che e1 op1 e2 op2 e3 op3 ...è equivalente a e1 op e2 and e2 op2 e3 and ...eccezione del fatto che ogni espressione viene valutata solo una volta. (A proposito, questa semplice regola ha l'effetto collaterale confuso che dichiarazioni come a == b is Truenon hanno più l'effetto desiderato.)

2
@RobertHarvey re:answerQuesto è stato dove anche la mia mente è andata immediatamente a commentare la domanda principale. Non considero il supporto per x < y < zl'aggiunta di alcun valore specifico alla semantica della lingua. (x < y) && (y < z)è più ampiamente supportato, è più esplicito, più espressivo, più facilmente digeribile nei suoi componenti, più compostabile, più logico, più facilmente riformulato.
K. Alan Bates,

6

La maggior parte dei linguaggi tradizionali sono (almeno in parte) orientati agli oggetti. Fondamentalmente, il principio alla base di OO è che gli oggetti inviano messaggi ad altri oggetti (o loro stessi), e il destinatario di quel messaggio ha il controllo completo su come rispondere a quel messaggio.

Ora vediamo come implementeremo qualcosa del genere

a < b < c

Potremmo valutarlo rigorosamente da sinistra a destra (associazione associativa):

a.__lt__(b).__lt__(c)

Ma ora chiediamo __lt__il risultato di a.__lt__(b), che è a Boolean. Non ha senso.

Proviamo associativo:

a.__lt__(b.__lt__(c))

No, neanche questo ha senso. Ora abbiamo a < (something that's a Boolean).

Va bene, che ne dici di trattarlo come zucchero sintattico. Facciamo in modo che una catena di n <confronti invii un messaggio n-1-ary. Questo potrebbe significare, inviamo il messaggio __lt__a a, passando be ccome argomenti:

a.__lt__(b, c)

Va bene, funziona, ma qui c'è una strana asimmetria: aarriva a decidere se è inferiore a b. Ma bnon arrivare a decidere se è inferiore c, invece, che la decisione è anche fatta da a.

Che ne dite di interpretarlo come un messaggio n-ary inviato a this?

this.__lt__(a, b, c)

Finalmente! Questo può funzionare. Significa, tuttavia, che l'ordinamento degli oggetti non è più una proprietà dell'oggetto (ad es. Se aè inferiore a quello che bnon è né una proprietà ané di b) ma piuttosto una proprietà del contesto (cioè this).

Da un punto di vista mainstream che sembra strano. Tuttavia, ad esempio in Haskell, è normale. Possono esserci più implementazioni diverse della Ordtypeclass, ad esempio, e se aè inferiore o meno b, dipende dall'istanza di typeclass che rientra nell'ambito.

Ma in realtà, non è che strano a tutti! Sia Java ( Comparator) che .NET ( IComparer) dispongono di interfacce che consentono di iniettare la propria relazione di ordinamento, ad esempio in algoritmi di ordinamento. Pertanto, riconoscono pienamente che un ordinamento non è qualcosa che è fissato a un tipo, ma dipende dal contesto.

Per quanto ne so, al momento non ci sono lingue che eseguono tale traduzione. Esiste tuttavia una precedenza: sia Ioke che Seph hanno quelli che i loro progettisti chiamano "operatori trinari" - operatori sintatticamente binari, ma semanticamente ternari. In particolare,

a = b

non viene interpretato come l'invio del messaggio =al apassaggio bcome argomento, ma piuttosto come l'invio del messaggio =al passaggio "Terra corrente" (un concetto simile ma non identico this) ae bcome argomenti. Quindi, a = bviene interpretato come

=(a, b)

e non

a =(b)

Questo potrebbe essere facilmente generalizzato agli operatori n-ary.

Nota che questo è davvero peculiare delle lingue OO. In OO, abbiamo sempre un singolo oggetto che è in definitiva responsabile dell'interpretazione di un messaggio inviato e, come abbiamo visto, non è immediatamente ovvio per qualcosa come l' a < b < coggetto che dovrebbe essere.

Ciò non si applica ai linguaggi procedurali o funzionali. Ad esempio, in Scheme , Common Lisp e Clojure , la <funzione è n-ary e può essere chiamata con un numero arbitrario di argomenti.

In particolare, <fa non medio "inferiore", piuttosto queste funzioni vengono interpretati in modo leggermente diverso:

(<  a b c d) ; the sequence a, b, c, d is monotonically increasing
(>  a b c d) ; the sequence a, b, c, d is monotonically decreasing
(<= a b c d) ; the sequence a, b, c, d is monotonically non-decreasing
(>= a b c d) ; the sequence a, b, c, d is monotonically non-increasing

3

È semplicemente perché i progettisti del linguaggio non ci hanno pensato o non hanno pensato che fosse una buona idea. Python lo fa come descritto con una semplice (quasi) LL (1) grammatica.


1
Ciò analizzerà comunque una normale grammatica in quasi tutti i linguaggi tradizionali; semplicemente non sarà compreso correttamente per il motivo dato da @RobertHarvey.
Mason Wheeler,

@MasonWheeler No, non necessariamente. Se le regole sono scritte in modo tale che i confronti siano intercambiabili con altri operatori (diciamo, perché hanno la stessa precedenza), allora non otterrai il comportamento giusto. Il fatto che Python stia mettendo tutti i confronti su un livello è ciò che gli consente di trattare la sequenza come una congiunzione.
Neil G,

1
Non proprio. Inserisci 1 < 2 < 3in Java o C # e non hai problemi con la precedenza dell'operatore; hai un problema con i tipi non validi. Il problema è che questo analizzerà comunque esattamente come l'hai scritto, ma hai bisogno di una logica di caso speciale nel compilatore per trasformarla da una sequenza di confronti individuali in un confronto concatenato.
Mason Wheeler,

2
@MasonWheeler Quello che sto dicendo è che la lingua deve essere progettata per funzionare. Una parte di questo è ottenere la grammatica giusta. (Se le regole sono scritte in modo tale che i confronti siano intercambiabili con altri operatori, diciamo, perché hanno la stessa precedenza, non otterrai il comportamento giusto.) Un'altra parte di ciò è interpretare l'AST come una congiunzione, che C ++ non lo fa. Il punto principale della mia risposta è che è una decisione del designer linguistico.
Neil G,

@MasonWheeler Penso che siamo d'accordo. Stavo solo evidenziando che non è difficile ottenere la grammatica giusta per questo. Si tratta solo di decidere in anticipo che si desidera che funzioni in questo modo.
Neil G,

2

Il seguente programma C ++ compila nary a peep da clang, anche con avvertenze impostate al livello più alto possibile ( -Weverything):

#include <iostream>
int main () { std::cout << (1 < 3 < 2) << '\n'; }

La suite di compilatori gnu, d'altra parte, mi avverte bene che comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses].

Quindi, la mia domanda è questa: perché x <y <z non è comunemente disponibile nei linguaggi di programmazione, con la semantica prevista?

La risposta è semplice: compatibilità all'indietro. Esiste una grande quantità di codice in natura che usa l'equivalente di 1<3<2e si aspetta che il risultato sia vero.

Un designer linguistico ha solo una possibilità per ottenere questo "giusto", ed è questo il momento in cui il linguaggio viene progettato per la prima volta. Inizialmente "sbagliato" significa che gli altri programmatori trarranno piuttosto rapidamente vantaggio da quel comportamento "sbagliato". Farlo "bene" la seconda volta interromperà quella base di codice esistente.


+1 perché questo programma genera "1" come risultato di un'espressione che è ovviamente falsa in matematica. Sebbene sia inventato, un esempio del mondo reale con nomi variabili incomprensibili diventerebbe un incubo di debug se questa funzionalità del linguaggio fosse aggiunta.
Seth Battin,

@SethBattin - Questo non è un incubo di debug in Python. L'unico problema in Python è if x == y is True : ..., la mia opinione: le persone che scrivono quel tipo di codice meritano di essere sottoposte a qualche tipo di tortura straordinaria e straordinaria che (se fosse vivo ora) renderebbe Torquemada stesso svenuto.
David Hammen,
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.