2016-12-04 2 views
2

Я читаю the closure examples in the Rust book. Для следующего примера кода:Как аргумент передается через закрытие и функцию?

fn factory() -> Box<Fn(i32) -> i32> { 
    let num = 5; 

    Box::new(move |x| x + num) 
} 

fn main() { 
    let f = factory(); 
    let answer = f(1); 
    assert_eq!(6, answer); 
} 

Завод является функция, которая принимает аргумент 0, но при связывании factory() к f, почему может f(1) поставить аргумент 1 на завод?

ответ

5

Это не так. У вас может быть неправильная ментальная модель того, как работают замыкания.

Закрытие представляет собой просто синтаксическую короткую руку для функции с дополнительным начальным аргументом, который захватывает значения из определяющей среды. Мы можем переписать пример на то, что является логически эквивалент:

fn factory() -> Box<Closure> { 
    let num = 5; 

    Box::new(Closure { num: num }) 
} 

struct Closure { 
    num: i32, 
} 

impl Closure { 
    pub fn invoke(&self, x: i32) -> i32 { 
     x + self.num 
    } 
} 

fn main() { 
    let f = factory(); 
    let answer = f.invoke(1); 
    assert_eq!(6, answer); 
} 

Обратите внимание, как num получает захвачены в «замыкание» в точке «закрытия» строится. Тело замыкания обращается к нему через self (который отмахивается для реальных закрытий).

Единственное различие между это и исходным кодом является то, что:

  1. Тип Closure существует, но анонимного. То есть вы не можете называть тип напрямую, и, следовательно, вы должны использовать Fn(i32) -> i32 в возвращаемом типе.

  2. Из-за вышеизложенного мы возвращаем коробчатый конкретный тип, а не объект в виде штриховки. Что касается того, как используется «закрытие», это не имеет большого значения для нас. Причина, по которой мы не можем вернуться Box<Fn(i32) -> i32>, состоит в том, что ...

  3. Мы не реализуем Fn. Этого еще нельзя сделать в стабильном коде. Если бы мы могли, это было бы почти идентично методу invoke.

  4. Мы определяем тело «замыкания» вне функции factory. Тем не менее, это просто синтаксическая разница: тело замыкания больше не является «частью» вашего factory, чем тело invoke является «частью» для выполнения этогоfactory.

Итак, мы надеемся, вы можете увидеть, что выполнение делает не возврата к функции factory: она переходит в другую функцию, которая просто случается определяется в factory ради удобства.

+0

Это очень полезно! Благодарю. – enaJ

Смежные вопросы