Sto cercando di creare una soluzione a Graham´s accumulator factory challenge che fondamentalmente richiede una funzione per restituire una chiusura che si chiude su una variabile numerica mutabile il cui valore iniziale viene ricevuto attraverso un parametro. Ogni chiamata a questa chiusura incrementa questa variabile acquisita di un valore che è un parametro della chiusura e restituisce il valore accumulato.Ripristino di una chiusura con ambiente mutabile
Dopo aver letto il closures RFC e alcune domande sulla restituzione di chiusure non archiviate (in particolare this). Potrei finalmente trovare una soluzione che sia stata compilata, ma il risultato non è quello che mi aspetterei.
#![feature(unboxed_closures, unboxed_closure_sugar)]
fn accumulator_factory(n: f64) -> Box<|&mut: f64| -> f64> {
let mut acc = n;
box |&mut: i: f64| {
acc += i;
acc
}
}
fn main() {
let mut acc_cl = accumulator_factory(5f64);
println!("{}", acc_cl.call_mut((3f64,)));
println!("{}", acc_cl.call_mut((3f64,)));
}
AFAIK questa chiusura cattura acc
dal valore, la struct generato che agisce come l'ambiente è mutevole e acc_cl
dovrebbero mantenere la stessa istanza ambiente tra le chiamate.
Ma il risultato stampato è 6
in entrambi i casi, quindi sembra che il valore modificato non sia persistente. E ciò che è più confuso è come viene calcolato questo risultato. Ad ogni esecuzione della chiusura il valore iniziale di acc
è 3
anche se n
è 5
quando chiamato.
Se modificare il generatore a questo:
fn accumulator_factory(n: f64) -> Box<|&mut: f64| -> f64> {
println!("n {}", n);
let mut acc = n;
box |&mut: i: f64| {
acc += i;
acc
}
}
quindi l'esecuzione ritornano sempre 3
e il valore iniziale di acc
è sempre 0
all'entrata chiusura.
Questa differenza di semantica sembra un bug. Ma a parte questo, perché l'ambiente si resetta tra le chiamate?
Questo è stato eseguito con rugc 0.12.0.
per un altro approccio è possibile controllare questa soluzione: https://github.com/Hoverbear/rust-rosetta/blob/master/src/accumulator_factory.rs. Le nuove chiusure unboxed in ruggine sono zucchero per una struttura e un'implementazione di tratto. Questa versione scrive la lunga versione "unsugared" –