Rust 如何在用作函数结果的闭包中应用trait

Rust 如何在用作函数结果的闭包中应用trait,rust,Rust,我无法实现这个LISP结构 (defun foo (n) (lambda (i) (incf n i))) 锈迹斑斑。 我试过: 如果您不需要函数调用,可以使用自己的类型包装x: use std::ops::Add; struct Adder<X> { x: X } impl<X: Copy> Adder<X> { fn add<Y: Add<X>>(&self, y: Y) -> <Y

我无法实现这个LISP结构

(defun foo (n)
  (lambda (i) (incf n i)))
锈迹斑斑。 我试过:


如果您不需要函数调用,可以使用自己的类型包装
x

use std::ops::Add;

struct Adder<X> { 
    x: X 
}

impl<X: Copy> Adder<X> {
    fn add<Y: Add<X>>(&self, y: Y) -> <Y as Add<X>>::Output {
        y + self.x
    }
}

fn main() {
    let x = Adder { x: 1usize };

    x.add(2); // as opposed to x(2)
}
使用std::ops::Add;
结构加法器{
x:x
}
impl加法器{
fn添加(&self,y:y)->:输出{
y+self.x
}
}
fn main(){
设x=加法器{x:1usize};
x、 添加(2);//与x(2)相反
}

这意味着您可以摆脱
,而无需分配任何内容。在稳定的锈迹中不可能实现
Fn(..)
,并且不稳定的版本可能在未来的锈迹版本中损坏。查看以了解更多信息。

如果您同意不再使用函数调用,您可以使用自己的类型包装
x

use std::ops::Add;

struct Adder<X> { 
    x: X 
}

impl<X: Copy> Adder<X> {
    fn add<Y: Add<X>>(&self, y: Y) -> <Y as Add<X>>::Output {
        y + self.x
    }
}

fn main() {
    let x = Adder { x: 1usize };

    x.add(2); // as opposed to x(2)
}
使用std::ops::Add;
结构加法器{
x:x
}
impl加法器{
fn添加(&self,y:y)->:输出{
y+self.x
}
}
fn main(){
设x=加法器{x:1usize};
x、 添加(2);//与x(2)相反
}

这意味着您可以摆脱
,而无需分配任何内容。在稳定的锈迹中不可能实现
Fn(..)
,并且不稳定的版本可能在未来的锈迹版本中损坏。查看了解更多信息。

通用版本存在几个问题

首先,出现您提供的错误是因为仅
T:Add
不足以指定输出类型:您还需要对关联的类型
::output
施加约束(请参阅文档):

或者,您可以指定
T
的静态
,尽管这不必要地限制了代码的泛型性:

fn f<T: Add<Output=T> + 'static>(n: T) -> Box<Fn(T) -> T> {
    Box::new(move |i: T| n + i)
}
现在它编译了

一种可能的替代方法是返回按值获取其环境的闭包:

fn f<'a, T: Add<Output=T> + 'a>(n: T) -> Box<FnOnce(T) -> T + 'a> {
    Box::new(move |i: T| n + i)
}

现在我们指定,对于任何生存期
'b
必须与
T
求和,而不是
T
。在这里,我们使用
Add
trait被重载的事实来引用基元类型。这可能是此函数最通用的版本。

通用版本有几个问题

首先,出现您提供的错误是因为仅
T:Add
不足以指定输出类型:您还需要对关联的类型
::output
施加约束(请参阅文档):

或者,您可以指定
T
的静态
,尽管这不必要地限制了代码的泛型性:

fn f<T: Add<Output=T> + 'static>(n: T) -> Box<Fn(T) -> T> {
    Box::new(move |i: T| n + i)
}
现在它编译了

一种可能的替代方法是返回按值获取其环境的闭包:

fn f<'a, T: Add<Output=T> + 'a>(n: T) -> Box<FnOnce(T) -> T + 'a> {
    Box::new(move |i: T| n + i)
}

现在我们指定,对于任何生存期
'b
必须与
T
求和,而不是
T
。在这里,我们使用
Add
trait被重载的事实来引用基元类型。这可能是该函数最通用的版本。

fn f(n:T)->Box T+'a>
工作正常,例如:
assert\u eq!(6,ff(2)),但对我来说,
fnf2(n:T)->Box T+'a>
似乎没有用。我应该如何使用f2?@seb_odessa请阅读该示例下面的解释。我说它有问题,包括调用
Box
的问题。
fn f(n:T)->Box T+'a>
工作正常,例如:
assert\u eq!(6,ff(2)),但对我来说,
fnf2(n:T)->Box T+'a>
似乎没有用。我应该如何使用f2?@seb_odessa请阅读该示例下面的解释。我说它有问题,包括调用
Box
的问题。谢谢,但是实现一个fn返回一个没有helper结构的函数很有趣。谢谢,但是实现一个fn返回一个没有助手结构的函数是很有趣的。欢迎来到Rust中的泛型w.r.t.算术运算的痛苦!欢迎来到Rust中的泛型w.r.t.算术运算之痛!
<anon>:4:10: 4:37 error: the parameter type `T` may not live long enough [E0310]
<anon>:4     Box::new(move |i: T| n + i)
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:4:10: 4:37 help: see the detailed explanation for E0310
<anon>:4:10: 4:37 help: consider adding an explicit lifetime bound `T: 'static`...
<anon>:4:10: 4:37 note: ...so that the type `[closure@<anon>:4:19: 4:36 n:T]` will meet its required lifetime bounds
<anon>:4     Box::new(move |i: T| n + i)
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~
fn f<'a, T: Add<Output=T> + 'a>(n: T) -> Box<Fn(T) -> T + 'a> {
    Box::new(move |i: T| n + i)
}
fn f<T: Add<Output=T> + 'static>(n: T) -> Box<Fn(T) -> T> {
    Box::new(move |i: T| n + i)
}
<anon>:4:31: 4:32 error: cannot move out of captured outer variable in an `Fn` closure
<anon>:4     Box::new(move |i: T| n + i)
                                  ^
fn f<'a, T: Add<Output=T> + Copy + 'a>(n: T) -> Box<Fn(T) -> T + 'a> {
    Box::new(move |i: T| n + i)
}
fn f<'a, T: Add<Output=T> + 'a>(n: T) -> Box<FnOnce(T) -> T + 'a> {
    Box::new(move |i: T| n + i)
}
fn f<'a, T: 'a>(n: T) -> Box<Fn(T) -> T + 'a> where for<'b> &'b T: Add<T, Output=T> {
    Box::new(move |i: T| &n + i)
}