如何使结构可调用?

Анд*_*ких 11 implementation traits rust

#![feature(unboxed_closures)]
#![feature(fn_traits)]

struct foo;

impl std::ops::Add for foo {
    type Output = foo;
    fn add(self, x: foo) -> foo {
        println!("Add for foo");
        x
    }
}

impl Fn for foo {
    extern "rust-call" fn call(&self) -> Self {
        println!("Call for Foo ");
        self
    }
}

fn main() {
    let x = foo;
    let y = foo;
    x + y;

    x();
}
Run Code Online (Sandbox Code Playgroud)

我实现了Add特性,但我不明白如何将结构作为函数调用.我收到错误:

error[E0243]: wrong number of type arguments: expected 1, found 0
  --> src/main.rs:14:10
   |
14 |     impl Fn for foo {
   |          ^^ expected 1 type argument
Run Code Online (Sandbox Code Playgroud)

我是Rust的新手,无法找到如何让这件事发生的例子.

She*_*ter 15

完全阅读您正在实施的特征以了解如何实现它非常有用.的Fn*性状的定义为:

pub trait Fn<Args>: FnMut<Args> {
    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
Run Code Online (Sandbox Code Playgroud)

注意实现和定义之间的任何差异?我看到很多:

  1. 实现不提供值#[feature]!这就是编译器指向的内容.另请参见错误的类型参数:预期1但找到0

  2. 该实现没有实现supertrait Fn,它本身需要supertrait Args.FnMut就是将相关的类型 FnOnce声明.

  3. 实现忽略了定义具体类型FnOnce应该是什么.

  4. Output特征返回时实现返回Output.

  5. 实现不接受第二个参数Self.该参数包含传入的任何参数.

另外,Rust使用的类型Self::Output不是call,所以它应该是PascalCase.

#![feature(unboxed_closures)]
#![feature(fn_traits)]

struct Foo;

impl Fn<()> for Foo {
    extern "rust-call" fn call(&self, _args: ()) {
        println!("Call (Fn) for Foo");
    }
}

impl FnMut<()> for Foo {
    extern "rust-call" fn call_mut(&mut self, _args: ()) {
        println!("Call (FnMut) for Foo");
    }
}

impl FnOnce<()> for Foo {
    type Output = ();

    extern "rust-call" fn call_once(self, _args: ()) {
        println!("Call (FnOnce) for Foo");
    }
}

fn main() {
    let x = Foo;
    x();
}
Run Code Online (Sandbox Code Playgroud)

通常情况下,只有一个特征的实现会在其中包含有趣的代码,而其他特征实现将委托给它:

extern "rust-call" fn call(&self, args: ()) {
    println!("Foo called, took args: {:?}", args);
}

// ...

extern "rust-call" fn call_mut(&mut self, args: ()) {
    self.call(args)
}

// ...

extern "rust-call" fn call_once(self, args: ()) {
    self.call(args)
}
Run Code Online (Sandbox Code Playgroud)


Pau*_*och 9

通过实现 Deref,您可以模拟所需的行为。然后,您只需在参数周围使用括号并获取返回值,就像调用函数一样。

请参阅此线程:https ://users.rust-lang.org/t/callable-struct-on-stable/54689/6

相关部分(感谢crawdad):

fn main() {
    let func: Functionish = make_func();
    func();
}

fn make_func() -> Functionish {
    Functionish {
        f: Box::new(|| println!("printing")),
    }
}

struct Functionish {
    f: Box<dyn Fn()>,
}

impl std::ops::Deref for Functionish {
    type Target = dyn Fn();

    fn deref(&self) -> &Self::Target {
        &self.f
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我自己的代码中的一个不完整的示例,它采用参数,一个是引用,一个是可变引用。就我而言,闭包存储在 Rc 内,这需要奇数行,&(*self.function_container)因为我需要先进入 Rc,然后才能获取对闭包的引用。

pub struct FeelFunction {
  pub function_type: FunctionType,
  name_container: RefCell<String>,
  function_container: Rc<dyn Fn(&FeelValue, &mut NestedContext) -> FeelValue>
}

impl Deref for FeelFunction {
  type Target = dyn Fn(&FeelValue, &mut NestedContext) -> FeelValue;

  fn deref(&self) -> &Self::Target {
      &(*self.function_container)
  }
}
Run Code Online (Sandbox Code Playgroud)