2016-02-19 9 views
5

Quindi, ho appena letto this blog post e sono stato confuso dalla parte "ternario-operatore è associato a sinistra", quindi ho eseguito il codice di esempio in un interprete:Associata ternaria nidificata Associatività in php vs java

$arg = 'T'; 
$vehicle = (($arg == 'B') ? 'bus' : 
      ($arg == 'A') ? 'airplane' : 
      ($arg == 'T') ? 'train' : 
      ($arg == 'C') ? 'car' : 
      ($arg == 'H') ? 'horse' : 
      'feet'); 
echo $vehicle; 

e infatti restituisce horse che è la controintuitività che era il punto nel post del blog.

Per curiosità, ho quindi provato a "realizzare questo lavoro" riscrivendolo per adattarlo a ciò che pensavo che "associativo a sinistra" avrebbe voluto. Ho ottenuto questo (formattazione è strano, ma rende più chiaro, almeno nella mia testa):

$arg = 'T'; 
$vehicle = (($arg != 'B') ? 
       ($arg != 'A') ? 
        ($arg != 'T') ? 
         ($arg != 'C') ? 
          ($arg != 'H') ? 
           'feet' : 
          'horse' : 
         'car' : 
        'train' : 
       'airplane' : 
      'bus' 
); 
echo $vehicle; 

Ora, questo funziona come previsto, nel senso che ciò che mai il carattere $arg è restituisce il veicolo che inizia con quel personaggio (minuscolo ovviamente, ma qui non è importante).

Curioso ancora, perché non sono chiaro su PERCHÉ il primo non funziona, mi chiedevo se quest'ultimo fallirebbe in un linguaggio associativo destro, perché non sembra come sarebbe. Così l'ho testato in un interprete java. Codice qui per chi vuole provare a salvare qualche secondo.

class Main { 
    public static void main(String[] args) { 


    Character arg = 'a'; 
    String vehicle = ((arg == 'B') ? "bus" : 
         (arg == 'A') ? "airplane" : 
         (arg == 'T') ? "train" : 
         (arg == 'C') ? "car" : 
         (arg == 'H') ? "horse" : 
         "feet"); 
    System.out.println(vehicle); 
    vehicle = ((arg != 'B') ? 
        (arg != 'A') ? 
         (arg != 'T') ? 
          (arg != 'C') ? 
           (arg != 'H') ? 
           "feet" : 
          "horse" : 
         "car" : 
        "train" : 
       "airplane" : 
      "bus" 
    ); 
    System.out.println(vehicle); 
    } 
} 

Entrambi i formati funzionano in java. Quindi, cosa dà php? Ho sentito che sta essenzialmente valutando le principali uguaglianze come quella finale ($arg == 'H'). Ma se è così, significa che si comporta come se fosse

$vehicle = ((($arg == 'B') || ($arg == 'A') || ($arg == 'T') || 
      ($arg == 'C') || ($arg == 'H')) ? 'horse' : 'feet'); 

Questo non ha senso per me. Nel secondo esempio di php che ho dato, mi sono spostato solo dove le uguaglianze vanno, nidificando nella parte if true dell'espressione ternaria, invece della parte if false. Non vedo perché il primo metodo non funzionerebbe se il secondo lo fa. Questo sembra più un errore piuttosto che "questo è come dovrebbe funzionare", e sto solo interpretando male le cose, che devo essere.

NOTA: so che posso racchiudere tra parentesi le cose per forzare l'espressione da valutare nel modo in cui voglio (che apparentemente è giusto-associativa). Non sto cercando "come fare questo lavoro", voglio sapere perché non lo fa.

risposta

2

L'associazione sinistra-destra è la precedenza quando si uniscono più operatori insieme, ad es. A + B + C.

Per l'operatore ternario A ? B : C, questo ha solo significato quando l'operatore supplementare ternario sostituisce la C parte (o A parte):

A ? B : X ? Y : Z 
(A ? B : X) ? Y : Z <-- left-associative (PHP) 
A ? B : (X ? Y : Z) <-- right-associative (Java, C, C++, C#, Perl) 

Se l'operatore supplementare ternario è inserito nel mezzo (sostituendo B) , può avere solo un significato:

A ? X ? Y : Z : C 
A ? (X ? Y : Z) : C 

Ecco perché PHP e Java sono d'accordo sul secondo. Non è applicata alcuna regola associativa sinistra/destra.

+0

Oh, penso di vedere. Poiché 'X' non è' 0' o qualsiasi altra cosa che valuta 'false', la valutazione finale è quindi Y. Quindi nel primo caso '$ arg ==' B'' è' false' ... '$ arg == 'A'' è 'false' ...' $ arg ==' T'' è 'true' ...' treno' valuta su 'true' ...' car' valuta su 'true'. .. il valore finale è 'cavallo'? –

+0

@MiaoLiu Hai capito. --- Conclusione: l'operatore ternario sinistro-associativo è un progetto pessimo. O per riassumere il [blog collegato] (http: // eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design /): * PHP è design scadente *. Stai lontano. – Andreas

+0

Quindi, in Java, il ternario più profondamente annidato viene valutato per primo, quindi il risultato di tale espressione viene utilizzato come uno dei valori di ritorno dell'espressione esterna. Quindi l'espressione esterna verrà valutata e il valore di ritorno di quello verrà utilizzato per la successiva istruzione esterna, ecc. Corretto? – Ungeheuer