从涉及Rust中泛型的特征方法返回闭包 [英] Returning a closure from a trait method involving generics in Rust

查看:597
本文介绍了从涉及Rust中泛型的特征方法返回闭包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习Rust,并且遇到了一个涉及关闭的棘手问题。我已经获得了许多基本的关闭示例,但现在我已经走出了基本的加法器和调用示例,事情变得杂乱无章。这是我的代码的第一部分,它的工作原理如下:

  trait TransformationElt< T,F>其中F:Fn(T) - > T {
fn get_transform(&self) - >盒及LT; F> ;;

$ b $ pub结构AddSome {pub x:i64}

impl AddSome {
fn the_transform(&self) - >方框< Fn(i64) - > I64> {
Box :: new(| x:i64 | x + 1 as i64)
}
}

这成功返回一个堆分配闭包,它将加1,实现我们的 AddSome 类型。我想要 AddSome 来实现 TransformationElt ,特别是类型为 i64

  impl< F:Fn(i64) - > I64> TransformationElt< i64,F> AddSome {
fn get_transform(&self) - >盒及LT f是氟烃基; {
Box :: new(move | x:i64 | x + self.x as i64)
}
}

在经历了很多混乱和尝试不同的事情之后,我仍然无法编译它。我通常得到的错误是:

blockquote
src / lex / math / algebra / groups.rs:31:16:31:46 error:不匹配的类型:
预计 F
找到 [closure@src/lex/math/algebra/groups.rs:31 :16:31:46 self:_]
(期望的类型参数,
找到闭包)[E0308]

我如何解决这个看似基本的问题并实现我的变换类型?



最后一件事 - 我有理由让事情成为关闭。我打算编写它们等,等等,我真的需要更高阶的函数。 解决方案

阻止你,因为你试图对它撒谎。当我们说谎时,通过程序员看我们是非常好的。



你是怎么说谎的?你说过我要编写一个采用某种任意类型的方法(有一些限制),然后我要返回一个只包含该类型的方框。然后,您继续不是返回传入值的一个框;您只需编译器就可以插入包装垃圾。



下面是一个小例子:

  fn wrapper< F>(f:F) - >盒及LT f是氟烃基; 
其中F:Fn(u8) - > u8
{
Box :: new(| x | f(x)+ 1)
}

fn main(){}

你真正想说的是你会返回一些实现这个特性的东西,但是没有描述如何(因为你不能指定一个闭包)。您可以通过间接方式(一个盒装的特质对象)来做到这一点:

  fn wrapper< F>(f:F) - >方框< Fn(u8) - > U8> 
其中F:Fn(u8) - > u8 +'static
{
Box :: new(move | x | f(x)+ 1)
}

fn main(){}






高度相关:


  1. 从函数返回闭包

  2. 从函数返回闭包

  3. 确定退货类型的封闭性


I'm learning Rust and have encountered a vexing issue involving closures. I've gotten a lot of the basic closure examples to work, but now that I've stepped out of the basic "make adder" and "call on" examples, things are getting messy. This is the first part of my code, which works:

trait TransformationElt<T, F> where F: Fn(T) -> T {
    fn get_transform(&self) -> Box<F>;
}

pub struct AddSome { pub x: i64 }

impl AddSome  {
    fn the_transform(&self) -> Box<Fn(i64) -> i64> {
        Box::new(|x: i64| x + 1 as i64)
    }
}

This successfully returns a heap-allocated closure that adds 1, implementing our AddSome type. I want AddSome to implement TransformationElt, specifically for the type i64:

impl<F: Fn(i64) -> i64> TransformationElt<i64, F> for AddSome  {
    fn get_transform(&self) -> Box<F> {
        Box::new(move |x: i64| x + self.x as i64)
    }
}

After much hackery and trying different things, I still can't get it to compile. The error I typically get is:

src/lex/math/algebra/groups.rs:31:16: 31:46 error: mismatched types: expected F, found [closure@src/lex/math/algebra/groups.rs:31:16: 31:46 self:_] (expected type parameter, found closure) [E0308]

How do I get around this seemingly basic issue and implement my "transform" type?

One final thing -- I have reasons I want to keep things as closures. I intend to compose them, etc. etc., things where I really do need higher-order functions.

解决方案

The compiler is stopping you because you are trying to lie to it. It's pretty good at seeing through us programmers when we lie.

How did you lie? You said "I'm going to write a method that takes some arbitrary type (with some restrictions) and then I'm going return a box containing only that type". You then proceeded to not return a box of the passed in value; you inserted wrapper junk, as far as the compiler cares.

Heres a small example:

fn wrapper<F>(f: F) -> Box<F>
    where F: Fn(u8) -> u8
{
    Box::new(|x| f(x) + 1)
}

fn main() {}

What you really want to say is that you will return something that implements the trait, but without describing how (because you can't specify a closure). You do this with indirection, a boxed trait object:

fn wrapper<F>(f: F) -> Box<Fn(u8) -> u8>
    where F: Fn(u8) -> u8 + 'static
{
    Box::new(move |x| f(x) + 1)
}

fn main() {}


Highly related:

  1. Return a closure from a function
  2. Returning a closure from a function
  3. Figuring out return type of closure

这篇关于从涉及Rust中泛型的特征方法返回闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆