2015-01-06 11 views
10

Stavo leggendo la descrizione dello strumento Scala WartRemover ed ero confuso da uno dei punti che avevano. La descrizione diceva:La trasparenza referenziale di interruzione di ritorno?

return interruzioni di trasparenza referenziale. Refactor per terminare i calcoli in modo sicuro.

// Won't compile: return is disabled 
def foo(n:Int): Int = return n + 1 
def foo(ns: List[Int]): Any = ns.map(n => return n + 1) 

Questo non ha alcun senso per me, ed entrambi gli esempi guardare referenzialmente trasparente. C'è un modo in cui la parola chiave return rende più probabile che una funzione interrompa la trasparenza referenziale? Sto semplicemente fraintendendo il loro punto?

+0

Penso che l'avviso "return" abbia lo scopo di prevenire usi come "def f (x: Int): Int = ((w: Nothing) => 3) (return x) '(che è la funzione identity, non la costante' 3'). Mentre posso essere d'accordo con il bando 'return' (c'è qualche ragione per usarlo affatto nel puro codice?), Non direi che un" early return "infrange la trasparenza referenziale, dal momento che si potrebbe ottenere lo stesso effetto sfruttando una continuazione -passare la trasformazione. – chi

+1

@chi, call/cc o costrutti simili che consentono di ottenere un handle di prima classe sulla prosecuzione _implicit_ non sono neanche trasparenti. Essere passati una funzione di continuazione _esplicitamente_ è una storia completamente diversa. Che una trasformazione globale crei un programma referentially trasparente non implica che l'originale sia referenzialmente trasparente (altrimenti lo stato mutabile sarebbe anche RT). –

+0

@AndreasRossberg vedo. Probabilmente stavo confondendo la RT di 'return' con la purezza di' foo'. – chi

risposta

3

Al suo centro, la trasparenza referenziale riguarda la valutazione delle espressioni. Fondamentalmente, dice che se valuti un'espressione in un contesto, valuterà lo stesso valore se lo valuti in un contesto identico.

Tranne che le dichiarazioni di "ritorno" non valgono affatto. Causano la chiamata corrente del metodo di inclusione per valutare qualcosa. Non c'è modo che si adatti al concetto di trasparenza referenziale. L'affermazione "lancio" ha un problema simile.

Per gli esempi, il primo

def foo(n:Int): Int = return n + 1 

è benigno ma dettagliata e non idiomatica. Il secondo

def foo(ns: List[Int]): Any = ns.map(n => return n + 1) 

è molto più problematico. Se superata la lista vuota, restituisce la lista vuota. Se viene passato un elenco non vuoto, restituisce il valore dell'header della lista più 1.

+3

Perché il secondo è un problema? '= if (ns.isEmpty)() else ns.head + 1' ha lo stesso comportamento senza' return'? –

+0

Poiché la lettura ingenua (in cui il ritorno diventa la valutazione della funzione, piuttosto che il metodo) è ns.map (_ + 1), è quasi certamente ciò che il programmatore intendeva. Molto più probabile che il "ritorno" sia un Java-ismo randagio, piuttosto che la semantica che descrivi sono in realtà ciò che il programmatore intendeva dire. –

+1

Sono d'accordo che potrebbe essere un errore. Immagino che mi manchi la connessione con la rottura della trasparenza referenziale –

Problemi correlati