2015-06-27 5 views
9

Sto imparando Rust in questo momento e sembra che non sia possibile specificare una chiusura come parametro di funzione. Ecco quello che ho:Impossibile passare la chiusura come parametro

fn foo(a: i32, f: |i32| -> i32) -> i32 { 
    f(a) 
} 

fn main() { 
    let bar = foo(5, |x| { x + 1 }); 
    println!("{}", bar); 
} 

ottengo il seguente errore:

foo.rs:1:19: 1:20 error: expected type, found `|` 
foo.rs:1 fn foo(a: i32, f: |i32| -> i32) -> i32 { 

Va bene, quindi non mi piaceva la sintassi di chiusura. Questo è un po 'fastidioso, perché ora devo scrivere questo:

fn foo(a: i32, f: Box<Fn(i32) -> i32>) -> i32 { 
    f(a) 
} 

fn main() { 
    let bar = foo(5, Box::new(|x| { x + 1 })); 
    println!("{}", bar); 
} 

Allora, che sta succedendo? Ho letto in alcuni numeri diversi places che il primo esempio è valido, quindi questa sintassi del "parametro tipo di chiusura" è stata rimossa o sto facendo qualcosa di sbagliato?

risposta

6

La ruggine è stata sviluppata all'aperto sin dall'inizio e il linguaggio si è evoluto molto da allora. L'articolo Stack Overflow a cui stai collegando ha quasi 1 anno di età, che in tempo di arrugginimento pre-1.0 è lungo come una vita ... (pun intended)

La risposta più semplice sarebbe: tieni presente che un sacco di articoli, post di blog, risposte SO ... non sono più rilevanti perché la lingua è cambiata. Se provi una soluzione e non funziona, trova la sintassi più recente (come hai fatto!) E prosegui.

In questo caso specifico, this RFC documenta la modifica da |...| -> ... a Fn/FnMut/FnOnce(...) -> ....

A proposito, c'è un piano per uno sforzo comunitario per trovare articoli obsoleti e contrassegnarli esplicitamente come deprecati, in modo che questo particolare problema sia evitato. Non riesco a trovare il collegamento ad esso, però.

+1

[RFC 114] (https://github.com/rust-lang/rfcs/blob/master/text/0114-closures.md) è più rilevante per questo cambiamento rispetto a RFC 231, ma i dettagli di RFC 114 non sono attuali (ad esempio, 'Fn' è ora' FnMut' e 'FnShare' è ora' Fn'). –

+0

* contrassegnali esplicitamente come deprecati * - oppure chiedi all'altro risponditore di aggiornare la risposta^_ ^. L'ho fatto e è stato aggiornato in pochi minuti. Ora, questa domanda dovrebbe essere contrassegnata come duplicata? – Shepmaster

+0

Non avevo in mente QUI, ma piuttosto post di blog, in cui il contenuto non è aggiornabile dalla community. Potrebbe anche essere indesiderabile; per esempio, i post del blog di Niko Matsakis sono più relativi al processo di pensiero: lo terresti come un riferimento storico piuttosto che come un documento aggiornato. – mdup

4

Se qualcuno è interessato a questa domanda oggi, ecco la sintassi con i generici:

fn foo<F: Fn(i32) -> i32>(a: i32, f: F) -> i32 { 
    f(a) 
} 

fn main() { 
    let bar = foo(5, |x| { x + 1 }); 
    println!("{}", bar); 
} 

Oppure, usando tratto oggetti:

fn foo(a: i32, f: Box<Fn(i32) -> i32>) -> i32 { 
    f(a) 
} 

fn main() { 
    let bar = foo(5, Box::new(|x| { x + 1 })); 
    println!("{}", bar); 
} 

si dovrebbe preferire il primo.