问题 Rust中的函数是第一类对象吗?


函数可以作为参数传递吗?例如,在JavaScript中,您可以将函数作为参数传递,如下所示:

setInterval(function() { /*...*/ }, 1000);

7938
2017-07-26 15:07


起源



答案:


匿名功能就像 function() {} 在JavaScript中确实存在,您可以使用闭包语法来定义它们

|arg, arg2, arg3| {
  /* function body including optionally closed-over variables */
} 

请注意,推断出参数和返回类型!

无论他们是否是头等舱,都需要更多的探索。 默认情况下,函数会借用已关闭的变量。您可以使用a指定将这些值移动到函数中 move 关闭:

let num = 5;
let plus_num = move |x: i32| x + num;

重要的是,没有引用其环境的闭包,包括 move 闭包,不需要引用创建它们的堆栈框架。由于它们的尺寸未知,因此它们本身不是一流的物体。

您可以 Box 一个闭包并将其作为一个特征对象返回 Fn 特征

这回答了有关内容的简要总结 这本书 这解释了如何关闭封闭以及它们如何与环境相互作用。


9
2017-08-22 03:42



只是提醒链接不再存在 - Joe Pinsonault
更新以参考新书和新的闭包语法/规则(来自哇 - 2年前) - Nate
那么......那是“是”呢? - OrangeDog
我和未来的googlers谢谢你 - Joe Pinsonault
@OrangeDog希望不会过于轻率,但我试图表明它意味着固定大小的特质对象是一流的。 - Nate


答案:


匿名功能就像 function() {} 在JavaScript中确实存在,您可以使用闭包语法来定义它们

|arg, arg2, arg3| {
  /* function body including optionally closed-over variables */
} 

请注意,推断出参数和返回类型!

无论他们是否是头等舱,都需要更多的探索。 默认情况下,函数会借用已关闭的变量。您可以使用a指定将这些值移动到函数中 move 关闭:

let num = 5;
let plus_num = move |x: i32| x + num;

重要的是,没有引用其环境的闭包,包括 move 闭包,不需要引用创建它们的堆栈框架。由于它们的尺寸未知,因此它们本身不是一流的物体。

您可以 Box 一个闭包并将其作为一个特征对象返回 Fn 特征

这回答了有关内容的简要总结 这本书 这解释了如何关闭封闭以及它们如何与环境相互作用。


9
2017-08-22 03:42



只是提醒链接不再存在 - Joe Pinsonault
更新以参考新书和新的闭包语法/规则(来自哇 - 2年前) - Nate
那么......那是“是”呢? - OrangeDog
我和未来的googlers谢谢你 - Joe Pinsonault
@OrangeDog希望不会过于轻率,但我试图表明它意味着固定大小的特质对象是一流的。 - Nate


他们是一流的。与JavaScript相比,Rust有两种类型 - 函数和闭包。

fn first_class() {
    println!("function");
}

fn higher_kinded<F: FnOnce()>(cb: F) {
    cb();
}

fn main() {
    higher_kinded(first_class); // passing function
    higher_kinded(|| println!("closure")); // passing closure
}

6
2017-07-26 17:37



什么叫 FnOnce() 在里面 <> 做?是的 <> 像Java泛型? - Zelphir
我不确定我是否正确理解你的问题。 FnOncle没有电话。 <>中的文本是类型参数。 fn higher_kinded在很多方面都是泛型函数,类似于C ++模板函数或Java泛型。然后将类型参数称为F,其类型为FnOnce(),它是可调用对象的类型定义。 - PEPP


看来情况确实如此 描述 在参考手册中。

fn add(x: int, y: int) -> int {
  return x + y;
}

let mut x = add(5,7);

type Binop<'a> = |int,int|: 'a -> int;
let bo: Binop = add;
x = bo(5,7);

它还尝试了以下方法,它以相同的方式传递闭包和函数:

fn myproc(val: int) {
    println!("{}", val*10);
}

fn call_func(func: |int| -> ()) {
    func(3);
}

…
call_func(|x| {println!("{}", x)});
call_func(myproc);

-1
2017-07-26 17:40



链接已经死了:( - OrangeDog