2011-01-30 3 views
14

Lo so, ci sono otherquestions sulla dichiarazione goto introdotta in PHP 5.3.Quali sono i casi di utilizzo validi di goto in PHP?

Ma non ho trovato nessuna risposta decente, tutti erano del tipo "last resort", "xkcd", "evil", "bad", "EVIL !!!". Ma nessun esempio valido. Solo affermazioni che non ci sono usi. O affermazioni che ci sono alcuni rari casi d'uso (ancora, senza esempi).

Quindi, la domanda è: "Quali sono i casi di utilizzo validi di goto in PHP?". Answers for "Is goto evil?" non sono i benvenuti e verranno downvoted. Grazie :)

Oppure qualcuno ha un collegamento a un RFC in cui viene spiegata la decisione - non sono riuscito a trovarne uno.

+0

'goto' è utile come falso rosso nelle discussioni sull'utilità o sulla cattiveria dei costrutti del linguaggio, indipendentemente da qualsiasi uso pratico. – mario

+1

@mario: ho cercato di chiarire nella mia domanda che non mi interessa sapere se è malvagio. Tali domande sono una perdita di tempo. Sono interessato ad esempi concreti. E quindi ritengo che questa non sia una domanda "soggettiva o argomentativa". – NikiC

+0

@NikiC, Btw quando dici di essere uno "sviluppatore di core PHP"] (http://stackoverflow.com/users/385378/nikic), vuol dire che conosci C? – Pacerier

risposta

6

Un possibile utilizzo (che può tuttavia essere implementato con altri mezzi) è l'implementazione di finite state machine.

+1

Una macchina a stato finito è qualcosa come un parser? – NikiC

+1

http://en.wikipedia.org/wiki/Finite-state_machine – Mchl

+0

Hm, questo non mi aiuta molto. Potresti dare un esempio di una macchina a stati finiti o dove è usata? L'articolo di Wiki è piuttosto teorico, non ho trovato un'applicazione qui. – NikiC

2

goto L'operatore può essere utilizzato per interrompere loop multi-livello.

Questo particolare esempio goto applicazione è dato at goto manual page:

Non è inoltre possibile saltare in qualsiasi tipo di ciclo o struttura switch. Puoi saltare fuori da questi e un uso comune è usare un goto al posto di un'interruzione multi-livello.

+3

Non abbiamo 'break x; 'per quello? 'pausa 4;' romperà quattro anelli. [Manuale per 'break'] (http://php.net/break) – NikiC

+0

Sì, lo abbiamo.BTW, se usato correttamente, 'goto' può portare a un codice un po 'più chiaro di' break x'. Forse questo è un tentativo di fornire un meccanismo di rottura simile a break/continue etichettati in Java. – Kel

+3

Apprezzerei un esempio in cui un 'goto' è più pulito quando un' break x'. Non riesco a immaginarne uno io. – NikiC

2

Goto è stato in gran sostituito da dichiarazioni specializzati come continue, break, try...catch. Negli anni in cui sto lavorando con PHP, non pensavo potesse aiutarmi una volta. In linguaggi come il C++ che non hanno l'istruzione break x, possono essere usati per saltare fuori da cicli annidati, ma dal momento che PHP lo ha, non c'è motivo.

Code Complete ha un capitolo molto bello e dettagliato su gotos. Citando gli ultimi due paragrafi:

L'uso di gotos è una questione di religione. Il mio dogma è che nelle lingue moderne è possibile sostituire facilmente nove gotos su dieci con costrutti sequenziali equivalenti. In questi casi semplici, dovresti sostituire il gotos per abitudine. Nei casi difficili, è ancora possibile esorcizzare il goto in nove casi su dieci: è possibile suddividere il codice in routine più piccole, utilizzare try-finally, utilizzare if annidati, testare e ritestare una variabile di stato o ristrutturare un condizionale. Eliminare il goto è più difficile in questi casi, ma è un buon esercizio mentale e le tecniche discusse in questa sezione ti forniscono gli strumenti per farlo.

Nel restante caso su 100 in cui un goto è una soluzione legittima al problema, documentarlo chiaramente e utilizzarlo. Se hai gli stivali da pioggia, non vale la pena camminare intorno all'isolato per evitare una pozzanghera di fango. Ma tieni la mente aperta agli approcci goto-less suggeriti da altri programmatori. Potrebbero vedere qualcosa che non fai.

Trovo molto difficile capire perché il team di PHP si sia preso la briga di aggiungerlo del tutto (dopo tutti quegli anni abbiamo vissuto in pace senza di esso).

+4

In PHP tuttavia 'goto' è stato aggiunto quando tutte le dichiarazioni che hai menzionato sono già state a lungo disponibili. Da qui la domanda che presumo. – Mchl

+0

@Mchl, esattamente. La domanda è perché è stato aggiunto "goto". – Pacerier

5

Vedi PHP Architect - GOTO in PHP 5.3: is it Really That Evil?

Questo articolo fornisce una breve panoramica del perché GOTO può essere utile, perché abbiamo in PHP (dal 2004) e perché era/è controversa. La risposta generale sembra essere: GOTO è in gran parte inutile e deve essere evitato a meno che in spazi di applicazione molto stretti (come la costruzione di un compilatore):

Una cosa è certa: ci sono alcune applicazioni in cui un buon sviluppatore può mettere GOTO è utile per produrre codice più semplice ed efficiente, ma probabilmente non è il tipo di programmi mainstream che il tuo sviluppatore medio scriverà; quindi, vi è una preoccupazione legittima qui che i programmatori inesperti useranno GOTO a detrimento generale del loro codice.

vedere anche alcune delle discussione newslist/controversie originale citato nell'articolo:

vedere anche questa lingua approfondita discussione agnostica su GOTO considered harmful at C2 Wiki

+1

Ok, quindi ancora un automa a stati finiti, lexing, analisi, compilazione. Questo sembra essere il caso d'uso numero uno (o anche l'unico). – NikiC

+0

@nikic si. assolutamente. – Gordon

3

Un caso in cui lo uso quando ho il controllo a più livelli da fare e non voglio aggiungere altro codice quando potrei semplicemente passare alla sezione pertinente dopo i miei controlli.

Ad esempio, c'è questo sistema che controlla lo stato di varie macchine in un magazzino e non riesce nel suo insieme nel suo complesso e invia un avviso se una qualsiasi parte di un sistema è morta, in pseudo-codice va in questo modo:

if(hsensor[status] != OK) { 
    alert = Humidity sensor hsensor[fail_id] failed with error hsensor[fail_error] 
    goto sendAlert; 
} 

if(cosensor[status] != OK) { 
    alert = Co2 sensor cosensor[fail_id] failed with error cosensor[fail_error] 
    goto sendAlert; 
} 

questo modo, se qualcosa fallisce, posso ignorare tutti gli altri controlli e proseguire dritto fino alla segnalazione. Chiunque stia chiamando riceve l'avviso e recupera il risultato completo di qualsiasi funzione chiamata avviso in modo che possa risolverlo.

+2

Questo è il miglior caso d'uso che io conosca. L'alternativa è una serie di istruzioni nidificate if o una variabile di stato globale che si controlla in ogni istruzione if. Secondo me, goto è il modo più pulito per ottenere questo risultato. –

+1

Amico, questa dovrebbe essere la risposta accettata. – Pacerier