如何使用括号进行泛型?

dsp*_*pyz 6 generics templates call lifetime rust

我收到了编译错误:

当与Fn特征族一起使用时,角括号表示法不稳定,请使用括号[E0215]

这是什么意思?我如何"使用括号"?

use std::hash::Hash;
use std::collections::HashMap;

struct MemoedFun<A, R> {
    fun: fn(&A) -> R,
    map: HashMap<A, R>,
}

fn memoize<A: Eq + Hash, R>(fun: fn(&A) -> R) -> MemoedFun<A, R> {
    MemoedFun {
        fun: fun,
        map: HashMap::new(),
    }
}

impl<'a, A, R> FnOnce<A> for &'a MemoedFun<A, R> {
    type Output=&'a R;
}
Run Code Online (Sandbox Code Playgroud)

Vla*_*eev 8

您的代码有几个问题.

首先,你不能Fn*直接在稳定的Rust中使用traits.这包括1)使用尖括号表示法,以及2)实现这些特征.但是,可以在不稳定的Rust中为这两个东西启用功能标志.

其次,如果对闭包特征使用尖括号,则必须使用元组作为参数,即使只有一个参数:

FnOnce<(A,)>
Run Code Online (Sandbox Code Playgroud)

第三,错误信息是,而不是FnOnce<(T, U), Output=V>你应该写FnOnce(T, U) -> V.这就是"使用括号"消息的含义.我同意这条消息在这里有误导性,因为Fn由于相关类型而无法实现此类消息.我想有关实现Fn类型的错误应优先于此错误.

第四,当你使用时,你将无法做你想要的(一个由哈希映射支持的记忆功能),&'a MemoedFun<A, R>因为你需要一个可变指针来更新地图.您需要实现FnOnce&'a mut MemoedFun<A, R>:

impl<'a, A: Eq + Hash, R> FnOnce<(A,)> for &'a mut MemoedFun<A, R> {
    type Output = &'a R;

    extern "rust-call" fn call_once(self, (arg,): (A,)) -> &'a R {
        if self.map.contains_key(&arg) {
            &self.map[&arg]
        } else {
            let r = (self.fun)(&arg);
            self.map.entry(arg).or_insert(r)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,你必须编写使用这个memoizer的结果代码并不漂亮.由于某种原因,您无法在"函数"上使用函数语法,因此您需要call_once()直接使用:

fn computer(x: &i32) -> i32 {
    println!("Computing for {}", x);
    -*x
}

let mut f = memoize(computer);

println!("f(10): {}", (&mut f).call_once((10,)));
println!("f(10): {}", (&mut f).call_once((10,)));
println!("f(42): {}", (&mut f).call_once((42,)));
Run Code Online (Sandbox Code Playgroud)

(在这里试试)

Fn*毕竟,特征手动实施不稳定是有原因的.