2015-09-06 9 views
5

Oggi ho imparato che nel Pharo l'esecuzione di:È ok per eseguire l'intero blocco di garanzia se il processo è terminato?

[v := 1] ensure: [self halt. v := 2] 

finirà impostazione v = 2, anche quando si abbandona il processo alla finestra halt (!).

Trovo che questo sia discutibile. Per me, la semantica di #ensure: significa che la sequenza

self halt. v := 2 

deve essere eseguito, a prescindere dalle circostanze con il blocco ricevente, non indipendentemente la logica del blocco tesi. E poiché la logica di #halt include l'evento di terminare il processo, trovo invadente la valutazione ostinata della seconda frase.

Dopo ho provato quanto segue: (. Stessa con #halt)

[v := 1] ensure: [1/0. v := 2] 

Quando il ZeroDivide eccezione spuntato-up I chiuso il debugger e ancora il valore di v era 2

Infine, valutato:

[v := 1] ensure: [n := 1/0. v := v + n] 

e chiuso il debugger su ZeroDivide eccezione. Questa volta il valore di v era 1 ma non ho ottenuto alcuna eccezione dal fatto che non è possibile valutare v + n. In altre parole, l'errore è andato in silenzio.

Quindi la mia domanda è. Qual è la logica dietro questo comportamento? Il processo non dovrebbe terminare al punto in cui verrebbe risolto in circostanze "normali", cioè senza lo #ensure: coinvolto?

+1

Non vedo la tua domanda nella mailing list degli sviluppatori di pharo. Sarebbe molto più appropriato lì (e nello squittio) che qui –

+2

@StephanEggermont: Il fatto che sia _also_ appropriato nella mailing list non lo rende _inappropriato_ qui. Secondo me, troppa conoscenza si perde in quelle mailing list ... non sono solo la cosa di tutti. ;-) –

+0

Non è appropriato perché ha bisogno di discussioni sul tradeoff della progettazione, non di risposte. Usiamo le mailing list per questo, non SO. Duplicare le cose qui va bene, ma il punto centrale è e rimane la mailing list (finché non creiamo qualcosa di meglio nell'immagine) –

risposta

4

Interessante. Sembra che la tua risposta risieda nel metodo BlockClosure>>valueNoContextSwitch, che viene chiamato da #ensure:. Se leggi il commento lì, dice che crea una copia esatta di BlockClosure>>value (in una primitiva), e viene restituito il valore di ritorno di quella copia, non il valore di ritorno del blocco originale contenente il tuo halt che hai terminato. Quindi la copia viene eseguita (apparentemente ignorando il copiato halt), anche se l'originale non finisce.

La mia ipotesi è che questo sia inteso a garantire (non è previsto il gioco di parole) che il blocco ensure: sia sempre eseguito, ma ha l'effetto collaterale non voluto di ignorare la chiusura del blocco originale. Sono d'accordo con te sul fatto che questo non solo è contro-intuitivo, ma probabilmente non è ciò che è stato inteso.

1

Immagino che questo sia un comportamento che non è completamente definito da alcuno standard (ANSI), ma correggimi, se sbaglio.

Altre Smalltalks sembrano comportarsi in modo diverso. L'ho provato in Smalltalk/X, dove il Debugger offre 3 opzioni: "Continua" (vale a dire procedere), "Interrompi" (ad esempio, svolgersi) e "Termina" (ad esempio, elimina il processo). Immagino che "Terminare" corrisponda a ciò che Squeak fa quando chiudi il debugger.

Con "Interrompi" e "Termina", il resto del blocco di garanzia NON viene eseguito, con "Continua" lo è. Immagino sia ok, e cosa ti aspetteresti.

In Interrompi e Termina (che sono entrambi svolti per gestori di eccezioni di corrispondenza), non dovrebbe tentare di rivalutare o procedere al blocco di potenziale potenzialmente errato/non valido/non riuscito.

È la scelta del gestore (che in pratica è il Debugger) se vuole procedere o meno. In caso contrario, dovrebbe uscire dal blocco di garanzia e continuare a eseguire qualsiasi altro blocco assicurativo che potrebbe trovarsi sopra nella catena chiamante.

Questo è coerente con il comportamento dei blocchi di gestione delle eccezioni, che non vengono neppure rivalutati o proceduti se viene sollevata la stessa eccezione. In ST/X, c'è un codice esplicito nelle classi di eccezione che si prende cura di questa situazione, quindi è decisamente per scopo e non per effetto collaterale.

La mia ipotesi è che questo sia sbagliato in Squeak e gli sviluppatori di Squeak dovrebbero essere informati.