当前位置: 首页 > 知识库问答 >
问题:

闭包的类型别名

卫甫
2023-03-14

我认为以下代码可以工作:

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);
}

但是我得到了一个编译器错误(见这里):

<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个答案

栾峰
2023-03-14

如果您的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
}
傅玮
2023-03-14

fn不定义闭包类型;它定义了裸函数指针(即指向使用fn关键字定义的函数的指针)。这就是为什么您不能将闭包分配给GradFn。相反,您希望使用FnFnMutFnonce

我需要再做一些更改才能编译此代码:

    < li >在< code>minimize上,您编写的< code>f参数通过值接收未调整大小的类型,这是禁止的。您还放置了一个不使用的< code>F类型参数。您可能想要约束< code>F并将< code>F用作< code>f的类型。 < li >编译器不允许我们在类型参数约束中使用类型别名;我们需要详细说明这一特征。这意味着类型别名基本上是无用的。 < li >我移除了< code>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);
}
 类似资料:
  • 闭包从封闭的作用中域捕获变量简单明了。这样会有某些后果吗?当然会。观察一下使用闭包作为函数参量的方式是要求为泛型的,它们定义的方式决定了这是必要的(原文:Observe how using a closure as a function parameter requires generics, which is necessary because of how they are defined):

  • 问题内容: 在Swift中,如果闭包仅包含单个语句,它将自动返回从该单个语句返回的值。 并非在所有情况下都感觉很自然。让我们看一个例子: 如您所见,即使闭包只应调用一个简单函数,它也会尝试自动返回其返回值,该返回值的类型为,与返回类型不匹配。 我可以通过实现闭包主体来避免这种情况: 感觉非常奇怪。 有没有更好的方法可以做到这一点,或者这仅仅是我必须忍受的东西? 问题答案: 发生这种情况的原因是单行

  • 我正在尝试获取部分应用的函数的列表,如下所示: 编译器向我产生一个错误: 错误[E0277]:类型std::vec::Vec的值 随后的尝试也没有成功: 1. 也只有这一次尝试最终成功了! 为什么在动态闭包方面类型推断如此糟糕? 为什么在第一次尝试中不起作用? 有没有更好的方法来利用类型推理来表达这样的想法?

  • 问题内容: 关门了 。这个问题需要更加集中。它当前不接受答案。 想要改善这个问题吗? 更新问题,使其仅通过编辑此帖子来关注一个问题。 5年前关闭。 改善这个问题 所有不同类型的SQL之间有什么区别?我听说过PostgreSQL,SQLite,MySQL,SQL等。它们之间有什么区别? 问题答案: SQL 是结构化查询语言,是一种数据库计算机语言,旨在管理关系数据库管理系统(RDBMS)中的数据。

  • 本节介绍的类型别名,就是通过关键字 type 给类型起个别名,类型别名较多应用于联合类型、交叉类型这种复合类型。 1. 慕课解释 类型别名会给类型起个新名字。类型别名有时和接口很像,但是可以作用于原始值,联合类型,元组以及其它任何你需要手写的类型。 用关键字 type 定义类型别名。 2. 举例说明 类型别名不会新建一个类型,而是创建一个新名字来引用此类型。 先看下面几个例子, 原始类型: typ

  • 为什么可以推断闭包表达式的参数类型和返回类型,而不是rust中的函数?