为闭包键入别名

时间:2014-12-22 06:54:24

标签: closures rust

我认为以下代码可行:

use std::num::{Num};
use std::fmt::{Show};

pub type GradFn<T : Num> = for<'a> fn(&'a [T]) -> (T, Vec<T>);

fn minimize<T : Show, F>(f : GradFn<T>, x0 : &[T]) {
    // some no-op to test types
    print!("{}",f(x0))
}

fn main() {
    let xSquared : GradFn<f64> = |x : &[f64]| -> (f64, Vec<f64>) {
        return (x[0] * x[0], vec![2.0 * x[0]]);
    };
    let (fx, grad)  = xSquared(vec![2.0f64].as_slice());
    print!("{}", fx);
}

但我收到编译错误(见here):

<anon>:12:32: 14:4 error: mismatched types: expected `fn(&'a [f64]) -> (f64, collections::vec::Vec<f64>)`, found `|&[f64]| -> (f64, collections::vec::Vec<f64>)` (expected extern fn, found fn)
<anon>:12   let xSquared : GradFn<f64> = |x : &[f64]| -> (f64, Vec<f64>) {
<anon>:13     return (x[0] * x[0], vec![2.0 * x[0]]);
<anon>:14   };

2 个答案:

答案 0 :(得分:4)

fn没有定义闭包类型;它定义了裸函数指针(即指向用fn关键字定义的函数的指针)。这就是为什么你不能为GradFn指定一个闭包的原因。相反,您要使用FnFnMutFnOnce

我需要做一些更改才能编译这段代码:

  • minimize上,您编写的f参数会按值接收未归类的类型,这是禁止的。您还会添加一个您不使用的F类型参数。您可能想要约束F并使用F作为f的类型。
  • 编译器不允许我们在类型参数约束中使用类型别名;我们需要完全阐明这个特征。这意味着类型别名基本上没用。
  • 我删除了xSquared上的类型注释,这是不必要的。这让我可以完全删除类型别名。

这是最终的代码:

#![feature(unboxed_closures)]

use std::num::{Num};
use std::fmt::{Show};

fn minimize<T: Show, F: FnMut(&[T]) -> (T, Vec<T>)>(mut f: F, x0: &[T]) {
    // some no-op to test types
    print!("{}", f(x0))
}

fn main() {
    let xSquared = |x: &[f64]| -> (f64, Vec<f64>) {
        return (x[0] * x[0], vec![2.0 * x[0]]);
    };
    let (fx, grad)  = xSquared(vec![2.0f64].as_slice());
    print!("{}", fx);
}

答案 1 :(得分:0)

如果你的GradFn实际上是一个裸函数指针(而不是闭包),你可以保留类型别名,如下所示:

use std::num::Num;
use std::fmt::Show;

// this type has to point to a bare function, not a closure
pub type GradFn<T> = for<'a> fn(&'a [T]) -> (T, Vec<T>);

fn minimize<T>(f : GradFn<T>, x0 : &[T]) 
    where T: Show + Num {
    // some no-op to test types
    println!("{}",f(x0))
}

fn main() {
    // this is now a bare function
    fn x_squared(x : &[f64]) -> (f64, Vec<f64>) {
        return (x[0] * x[0], vec![2.0 * x[0]]);
    }

    // and this is a pointer to it, that uses your type alias
    let x_sq : GradFn<f64> = x_squared;

    let (fx, grad)  = x_sq(&[2f64]);
    println!("fx: {} - grad: {}", fx, grad);

    minimize(x_sq, &[3f64]);; // works with minimize as well
}