从涉及Rust中泛型的特征方法返回闭包 [英] Returning a closure from a trait method involving generics in 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(){}
高度相关:
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:
- Return a closure from a function
- Returning a closure from a function
- Figuring out return type of closure
这篇关于从涉及Rust中泛型的特征方法返回闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!