Evidenziando l'importanza dell'ordine quando si utilizzano condizioni in cortocircuito

2

Stavo lavorando su un pezzo di codice quando ho notato che un'istruzione if poteva funzionare o bloccarsi in base all'ordine utilizzato per le parti connesse con and .

Puoi replicare il problema in questo modo:

boolean func(String x) {
    assert x
    return true
}
v = "text"

if (v != "" && func(v)) {
   println("Hello")
}

A seconda che venga utilizzato per primo v != "" o func(v) , if provoca un errore di asserzione o meno.

Questo perché Groovy controlla la prima espressione e se quella è già falsa non valuta nemmeno la seconda poiché e l'operatore causeranno sempre l'espressione falsa.

Quindi in groovy le condizioni collegate sono combinate in questo modo:

if (v != "") {
    if (func(v)) {
        *[...]*
    }
}

So che almeno alcuni altri linguaggi hanno un comportamento simile (credo che in Java si possa passare usando & o && ) ma mi chiedo è questa la strada da percorrere. Sembra abbastanza intuitivo da capire e non penso che trasmetta l'importanza dell'ordine in questa affermazione.

Come posso chiarire su base di codice che l'ordine è importante e deve essere preso in considerazione quando si altera il codice che lo circonda? O dovrei semplicemente dimenticarmene e supporre che le persone controllino qualcosa del genere?

Dopo aver svolto ulteriori ricerche, ho scoperto una voce sul sito di documentazione groovy di base per gli operatori: Groovy - Short Circuiting

Il termine generale sembra descrivere questa sembra essere una "valutazione di cortocircuito". Molto appropriato Ho adattato il titolo della domanda perché volevo inserirla ma non conoscevo la terminologia.

    
posta AK_is_curious 05.12.2017 - 18:28
fonte

2 risposte

6

Perché?

In C, C ++, Python, Java, C #, Groowy e Swift (ordine storico di apparizione), e certamente anche in molti altri linguaggi, il solito logico e operatore (principalmente && ) funziona con short- circuiti.

In alcune lingue come ADA (vale a dire and ), la forma di cortocircuito richiede uno sforzo supplementare (ad esempio and then , che dà un aspetto simile al tuo if -statements successivamente incorporato).

Il motivo di questo comportamento è ... corto circuito, per evitare guasti fatali senza un sacco di dichiarazioni aggiuntive. I designer di lingue hanno valutato attentamente i pro e i contro:

Expressions connected bu && and || are evaluated left to right, and evaluation stops as soon as the truth or falsehood of the result is known. These properties are critical for writing programs that work.
- B.W.Kernighan & D.Ritchie, 1978, The C programming language, P.38

Ad esempio, l'istruzione follwing funziona in tutti i casi:

int a=10, b=0; 
if (b!=0 && a/b>3)   // ok
    ...

Se il connettore and sarebbe senza cortocircuito, tali precauzioni sarebbero inutili: entrambi i termini sarebbero valutati e il a/b innescherebbe una divisione fatale per 0 eccezione ...

if (b!=0 & a/b>3)   // ouch !!! 
    ...

Hai bisogno di preoccuparti?

Il mondo è composto da due tipi di programmatori: quelli che sono a conoscenza del cortocircuito e dell'ordine, e quelli che sono non ancora .

Quindi non preoccuparti, la maggior parte dei tuoi colleghi si prenderà cura dell'ordine. Se temi che qualcuno possa perdere qualcosa di importante, metti un commento:

if (b!=0 && a/b>3)   // order avoids divide by zero
    ...
    
risposta data 05.12.2017 - 21:20
fonte
3

&& e || almeno in java (e credo anche in groovy) significano che l'operazione è cortocircuitata, cioè come hai detto che il lato destro sarà valutato se e solo se necessario.

& e | valgono entrambi i lati.

Quindi, se stai utilizzando && o || , significa già che l'ordine è importante. Nell'esempio, l'utilizzo di && implica che func(v) può essere valutato solo se v != "" è true.

    
risposta data 05.12.2017 - 18:49
fonte