2014-11-22 2 views
9

Учитывая следующие программы ржавчины:Как передать функцию в качестве аргумента в Русте

fn call_twice<A>(val: A, f: fn(A) -> A) -> A { 
    f(f(val)) 
} 

fn main() { 
    fn double(x: int) -> int {x + x}; 
    println!("Res is {}", call_twice(10i, double)); 
    // println!("Res is {}", call_twice(10i, (x: int) -> int {x + x})); 
    //^this line will fail 
} 

Почему я могу передать double как функция, но не встраивается? Каков хороший способ добиться такого же поведения, не определяя функцию где-нибудь?

ответ

13

2016-04-01 Обновление:

Как Руст 1.0, код должен выглядеть следующим образом:

fn call_twice<A, F>(val: A, mut f: F) -> A 
where F: FnMut(A) -> A { 
    let tmp = f(val); 
    f(tmp) 
} 

fn main() { 
    fn double(x: i32) -> i32 {x + x}; 
    println!("Res is {}", call_twice(10, double)); 
    println!("Res is {}", call_twice(10, |x| x + x)); 
} 

Переход к параметру закрытия, потому что закрытие является Теперь распакованным ,

Оригинал:

Насколько мне известно, вы не можете определить функции инлайн подобное.

Что вы хотите это закрытие. Следующие работы:

fn call_twice<A>(val: A, f: |A| -> A) -> A { 
    let tmp = f(val); 
    f(tmp) 
} 

fn main() { 
    fn double(x: int) -> int {x + x}; 
    println!("Res is {}", call_twice(10i, double)); 
    println!("Res is {}", call_twice(10i, |x| x + x)); 
} 

Есть несколько вещей, чтобы отметить:

  1. Функции принуждать к закрытию, но обратное не верно.

  2. Вам необходимо сохранить результат f(val) во временное из-за правил заимствования. Короткая версия: вам нужен уникальный доступ к закрытию, чтобы вызвать его, а средство проверки займа недостаточно велико, чтобы реализовать два вызова, независимо от их исходных позиций.

  3. Закрытия в настоящее время заменяются закрытыми замками, поэтому это изменится в будущем, но мы пока не совсем там.

+0

Спасибо за объяснение. Это немного странно с временной переменной, но я думаю, что это будет исправлено в более стабильной версии. –

+0

Это, похоже, не работает с ржавчиной 1.7: https://play.rust-lang.org/?gist=ad35b80eeae1d1966944a66a75d0ad80&version=stable –

+2

@SandeepDatta Этот ответ с 2014 года; этот код был бы недопустимым даже в Rust 1.0. Я обновил его. –

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