Tempo previsto per la valutazione lazy con funzioni annidate?

2

Un collega e io stiamo facendo un corso R gratuito, anche se credo che questo sia un problema di valutazione pigro più generale, e abbiamo trovato uno scenario che abbiamo discusso brevemente e mi piacerebbe trovare la risposta di una comunità più ampia .

Lo scenario è il seguente (pseudo codice):

wrapper => function(thing)
{
    print => function()
    {
        write(thing)
    }
}

v = createThing(1, 2, 3)
w = wrapper(v)
v = createThing(4, 5, 6)
w.print()
// Will print 4, 5, 6 thing.
v = create(7, 8, 9)
w.print()

// Stampa 4, 5, 6 perché "cosa" è stata ora valutata.

Un'altra situazione simile è la seguente:

// Using the same function as above
v = createThing(1, 2, 3)
v = wrapper(v)
w.print()
// The wrapper function incestuously includes itself.

Ora capisco perché questo accade ma dove io e il mio collega differiamo è su cosa dovrebbe accadere.

La vista del mio collega è che questo è un bug e la valutazione dell'argomento passato deve essere forzata nel momento in cui viene passata in modo che la funzione "w" restituita sia corretta.

Il mio punto di vista è che preferirei la sua opzione da solo, ma mi rendo conto che la situazione che stiamo incontrando dipende dalla valutazione pigra e questo è esattamente come funziona ed è più una stranezza che un bug. Non sono sicuro di cosa ci si aspetterebbe, quindi la ragione per cui sto facendo questa domanda. Penso che i commenti alle funzioni possano esprimere quello che accadrà, o lasciare che sia molto pigro, e se il codificatore che usa la funzione vuole che l'argomento sia valutato, allora possono forzarlo prima di passarlo.

Quindi, quando si lavora con evaulation pigro, qual è la pratica per il tempo di valutare un argomento passato e memorizzato, all'interno di una funzione?

    
posta Matt_JD 24.08.2014 - 12:10
fonte

1 risposta

1

Anche se non ho familiarità con R, sulla base del manuale sembra essere dovuto alla natura imperativa di R combinata nel modo in cui implementa la pigrizia. Vedi 4.3.3 Valutazione degli argomenti e 4.3.4 Ambito di applicazione .

Diamo un'occhiata all'esempio che hai:

wrapper =
  function(thing)
    function()
      print(thing)

Prima di tutto, nota che puoi chiamare

w = wrapper(v) // line A

senza nemmeno definire v prima. Quello che succede è che la funzione wrapper cattura un promessa , che consiste in 3 cose:

  • un valore (possibilmente assente),
  • un'espressione e
  • un puntatore all'ambiente .

Fino a quando qualcosa forza la valutazione della promessa, la promessa rimane non valutata e quindi il suo valore è assente. Una volta che la promessa è forzata, il valore viene compilato dal risultato della valutazione e non verrà mai più valutato. In altre parole, le promesse vengono valutate al massimo una volta. (C'è comunque qualche complicazione se la valutazione fallisce.)

La proprietà chiave è che una promessa contiene un puntatore per l'ambiente, non una copia di esso! Ciò significa che se l'ambiente lessicale cambia in seguito, anche il valore futuro della promessa potrebbe cambiare!

Quindi, se inserisci quanto segue dopo la riga A:

v = 10
w()

Vedrai che stamperà il valore 10 .

Sono d'accordo che questo è altamente non intuitivo, ma non credo che sia un bug neanche. Anche se lavoro regolarmente con Haskell (un altro linguaggio pigro), il linguaggio è progettato in modo tale che tali cose non possano accadere (in parte a causa della mancanza di impurità).

Penso che questo sia in gran parte un artefatto del fatto che le promesse tengono puntatori ai loro ambienti lessicali, piuttosto che una copia di esso. Ciò significa che in R gli argomenti non sono veramente "pass-by-value", né sono "pass-by-reference", né sono "pass-by-name"!

    
risposta data 24.08.2014 - 16:17
fonte

Leggi altre domande sui tag