Valutazione a corto circuito

(Reindirizzamento da Valutazione di McCarthy)

La valutazione a corto circuito, valutazione minima o valutazione di McCarthy è un meccanismo relativo agli operatori booleani binari per cui il secondo operando viene valutato unicamente se il valore del primo operando non è sufficiente da solo a determinare il risultato dell'espressione: quando il primo argomento dell'operatore logico AND è falso, il valore dell'intera espressione dovrà essere necessariamente falso; e quando il primo argomento dell'operatore logico OR è vero, il valore dell'intera espressione dovrà essere necessariamente vero. In alcuni linguaggi di programmazione (Lisp), i normali operatori booleani sono cortocircuitati. In altri (Ada, Java), sono disponibili sia operatori cortocircuitati che non. Per alcuni operatori booleani, come Disgiunzione esclusiva (XOR), non è possibile cortocircuitare, perché entrambi gli operandi sono sempre richiesti per determinare il risultato.

La valutazione a corto circuito, prevista in numerosi linguaggi di programmazione, è usata sia per sveltire il calcolo del risultato delle espressioni, sia come forma compatta di un'istruzione condizionale qualora la valutazione del secondo operando produca degli effetti collaterali.

Supporto nei comuni linguaggi di programmazione

modifica
Operatori booleani nei vari linguaggi
Linguaggio Operatori eager Operatori di cortocircuito Tipo di risultato
Advanced Business Application Programming (ABAP) nessuno and, or Booleano1
Ada and, or and then, or else Booleano
ALGOL 68 and, &, ∧ ; or, ∨ andf, orf (entrambi definiti dall'utente) Booleano
C, Objective-C nessuno &&, ||, ?[1] int (&&,||), opnd-dipendente (?)
C++2 &, | &&, ||, ?[2] Booleano (&&,||), opnd-dipendente (?)
C# &, | &&, ||, ?, ?? Booleano (&&,||), opnd-dipendente (?, ??)
ColdFusion Markup Language (CFML) nessuno AND, OR, &&, || Booleano
D3 &, | &&, ||, ? Booleano (&&,||), opnd-dipendente (?)
Eiffel and, or and then, or else Booleano
Erlang and, or andalso, orelse Booleano
Fortran4 .and., .or. .and., .or. Booleano
Go, Haskell, OCaml nessuno &&, || Booleano
Java, MATLAB, R, Swift &, | &&, || Booleano
JavaScript, Julia &, | &&, || Ultimo valore
Lasso nessuno and, or, &&, || Ultimo valore
Lisp, Lua, Scheme nessuno and, or Ultimo valore
MUMPS (M) &, ! nessuno Numerico
Modula-2 nessuno AND, OR Booleano
Oberon nessuno &, OR Booleano
OCaml nessuno &&, || Booleano
Pascal and, or5 and_then, or_else6 Booleano
Perl, Ruby &, | &&, and, ||, or Ultimo valore
PHP &, | &&, and, ||, or Booleano
Python &, | and, or Ultimo valore
Smalltalk &, | and:, or:7 Booleano
Standard ML Sconosciuto andalso, orelse Booleano
Visual Basic .NET And, Or AndAlso, OrElse Booleano
VBScript, Visual Basic, Visual Basic for Applications (VBA) And, Or Case di selezione8 Numerico
Wolfram Language And @@ {...}, Or @@ {...} And, Or, &&, || Booleano

1 ABAP non ha tipi booleani differenti.
2 In caso di overload, gli operatori && e || sono eager e possono ritornare qualunque tipo.
3 Questo vale solo per le espressioni valutate a runtime, static if e static assert. Le espressioni negli inizializzatori static o nelle costanti manifest usano la valutazione eager.
4 Gli operatori Fortran non sono né cortocircuitati né eager: le specifiche del linguaggio permettono al compilatore di selezionare il metodo per l'ottimizzazione.
5 Il Pascal esteso (ISO/IEC 10206:1990) permette, ma non richiede, il cortocircuito.
6 Il Pascal esteso (ISO/IEC 10206:1990 supporta and_then e or_else.[3]
7 Smalltalk usa la semantica del cortocircuito solo se l'argomento di and: è un blocco (es.: false and: [Transcript show: 'Non apparirò!']).
8 I linguaggi BASIC che hanno supportato le istruzioni CASE lo hanno fatto usando un sistema di valutazione condizionale, invece che tabelle di salto limitate ad etichette (label) fisse.

Usi comuni

modifica

Forma compatta di if/else

modifica

In uno script di shell:

test -d /tmp/foo || mkdir /tmp/foo

In questo caso il comando mkdir /tmp/foo viene eseguito unicamente se il risultato del primo comando (che verifica l'esistenza della directory /tmp/foo) è falso, per via della valutazione a corto circuito dell'operatore OR (indicato come || nello script). Rappresenta una forma compatta di

if ! test -d /tmp/foo; then mkdir /tmp/foo; fi

Evitare effetti indesirati del secondo argomento

modifica

Nel linguaggio C:

if (denom != 0 && num / denom)
{
    ... // assicura che l'espressione num / denom non risulti mai in un errore a causa del denominatore nullo (denom==0)
}

Si consideri il seguente esempio:

int a = 0;
if (a != 0 && myfunc(b))
{
    do_something();
}

In questo esempio, la valutazione a cortocircuito garantisce che myfunc(b) non venga mai chiamata. Questo perché l'espressione a != 0 risulta in false. Questa caratteristica permette due utili costrutti di programmazione. Come prima cosa, la prima sotto-espressione può essere usata per controllare se è necessario un ulteriore calcolo e se il risultato è false si possono eliminare i calcoli non necessari del secondo argomento. Secondariamente, permette un costrutto dove la prima espressione garantisce una condizione senza la quale la seconda espressione potrebbe causare un errore di runtime. Essi sono entrambi illustrati nei seguenti codici C dove la valutazione minima evita sia la dereferenziazione con puntatore nullo sia un eccesso di prelievi in memoria:

bool is_first_char_valid_alpha_unsafe(const char *p)
{
    return isalpha(p[0]); // SEGFAULT altamente probabile con p == NULL
}

bool is_first_char_valid_alpha(const char *p)
{
    return p != NULL && isalpha(p[0]); // a) nessuna necessità di eseguire isalpha() con p == NULL, b) nessun rischio di SEGFAULT 
}

Voci correlate

modifica
  Portale Informatica: accedi alle voci di Wikipedia che trattano di informatica