【问题标题】:How to instantiate a type that is based on a closure如何实例化基于闭包的类型
【发布时间】:2021-12-30 08:24:41
【问题描述】:

在我的项目中,我使用类型定义来保存具有特定函数签名的闭包,如下所示:

// Standardized function signature
pub type InternalOperation = impl Fn(Ast, Rc<RefCell<VTable>>, Rc<RefCell<FTable>>) -> Ctr;
pub struct ExternalOperation {
    // ...
    // The project is on gitlab called relish if you are interested
}

/* A stored function may either be a pointer to a function
 * or a syntax tree to eval with the arguments
 */
pub enum Operation {
    Internal(InternalOperation),
    External(ExternalOperation)
}

// function which does not need args checked
pub struct Function {
    pub function: Operation,
    // many more things like argument types and function name
}

我尝试实例化一个函数:

pub fn get_export(env_cfg: bool) -> Function {
    return Function{
        name: String::from("export"),
        loose_syms: true,
        eval_lazy: true,
        args: Args::Lazy(2),
        function: Operation::Internal(
            |a: Ast, b: Rc<RefCell<VTable>>, c: Rc<RefCell<FTable>>| -> Ctr {
                // so much logic here to manage variables in b
                // if env_cfg is true, entries in b are tied to environment variables 
        })
    }
}

但随后我收到以下错误:

error[E0308]: mismatched types
  --> src/vars.rs:49:13
   |
49 | /             |a: Ast, b: Rc<RefCell<VTable>>, c: Rc<RefCell<FTable>>| -> Ctr {
50 | |                 let inner = a.borrow_mut();
51 | |                 match &inner.car {
52 | |                     Ctr::Symbol(identifier) => {
...  |
96 | |                 return Ctr::None;
97 | |             }
   | |_____________^ expected opaque type, found closure
   |

我尝试过的:

  • 将 InternalOperation 声明为匿名函数。这可行,但我无法存储闭包。
  • 我尝试使用 InternalOperation(......) 声明闭包,根据语法规则这是不正确的

我在这里使用闭包,以便我的应用程序的用户配置可以在函数操作的主体中使用。是否可以以这种方式使用闭包,还是需要重构我的代码以以其他方式应用 env_cfg 值?

【问题讨论】:

  • 在类型别名中使用impl Trait 是不稳定的。你开启type_alias_impl_trait的功能了吗?

标签: rust closures


【解决方案1】:

我假设type_alias_impl_trait 功能已打开。如果没有,这段代码无论如何都不应该编译,因为没有这个特性 impl Trait 不允许在类型别名中。


理论上,此功能应将类型别名的任何使用视为“定义使用”,即我们可以从中推断出不透明类型的使用。在实践中,它(尚未)用于许多用途。 AFAIK,目前只有函数返回类型被认为是定义用途。

但是,在您的情况下,您希望编译器从表达式中推断出类型。 应该知道Operation::Internal的第一个字段是InternalOperation类型,因此应该知道InternalOperation是@987654328内部回调的类型@。 理论上这应该可行,除非编译器(当前)不应用这些知识。

您可以通过创建一个新函数来返回回调来解决此问题:

fn get_callback(env_cfg: bool) -> InternalOperation {
    |a: Ast, b: Rc<RefCell<VTable>>, c: Rc<RefCell<FTable>>| -> Ctr {
        // so much logic here to manage variables in b
        // if env_cfg is true, entries in b are tied to environment variables
    }
}
pub fn get_export(env_cfg: bool) -> Function {
    Function {
        name: String::from("export"),
        loose_syms: true,
        eval_lazy: true,
        args: Args::Lazy(2),
        function: Operation::Internal(get_callback(env_cfg)),
    }
}

【讨论】:

  • 当我将它重构为如下所示时,引用 get_callback 函数的返回值时出现相同的错误。
  • 这很奇怪,因为它does work 对我来说。你能提供更多背景信息吗?
  • 绝对。我向 gitlab 推送了一个 WIP 提交:gitlab.com/whom/relish 回调 getter 和 Function 实例在 src/vars.rs 中,类型定义在 src/funcs.rs 中。我的 rustc 版本是 1.59.0-nightly,type_alias_impl_trait 的功能节同时在 src/lib.rs 和 src/bin/main.rs 中,欢迎您提供任何见解!
  • 你使用了两次不同的闭包。它应该推断为一个,并且只有一个,类型。
  • 您能详细说明一下吗?我已经删除了该类型别名的所有其他使用,除了导出函数回调中使用的别名。我仍然遇到同样的错误。我不能将此类型别名与具有相同匹配签名的多个闭包一起使用,这是真的吗?如果是这样,我将需要删除此类型别名的使用并找到另一种引用闭包的方法。
猜你喜欢
  • 2021-12-06
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
相关资源
最近更新 更多