How can Rust create a function that receives structural methods?

Asked 3 months ago, Updated 3 months ago, 12 views

I'm a beginner studying Rust.
I'd like to create a function that receives structural methods, but I can't pass them to the function, so please give me some advice.

Tried

Receive Function - Rust by Example
http://doc.rust-jp.rs/rust-by-example-ja/fn/closures/input_functions.html
I created the following code by referring to .

structure Foo{
  s —String,
}
impl Foo {
  fn method(&self,s:&String){
    println!("{},s);
  }
}

fn function(s:&String) {
  println!("{},s);
}

fn execute<F> (f:F, s:&String)
where
  F: Fn(&String),
{
  f(s);
}

US>fnmain(){
  lets=String::from("function!");
  execute(function, & s);
  // >> function!

  lets=String::from("method!");
  let foo=Foo{s};
  execute(foo.method, & foo.s);
  // >>>
}

Results

execute(function,&s); is running, but the following error appears in the execute(foo.method,&foo.s); section:

 error [E0615]: attempted to take value of method `method` on type `Foo`
  -->src/main.rs:35:15
   |
35 | execute (foo.method, & foo.s);
   |               ^^^^^^ method, not a field
   |
help —use parents to call the method
   |
35 | execute(foo.method(_), & foo.s);
   |                     +++

However, what you want to do is not execute(foo.method(&foo.s); to "pass the return value of the method to the function."

How do I pass the structural method to a function?
Thank you for your cooperation.

rust

2022-09-30 13:57

2 Answers

If you specify a closure, you can do what you want (although the amount of description increases).

execute(|x|foo.method(x), & foo.s);

If you want to pass the function itself:
However, since the method function takes two arguments: self and s, the function that receives the method needs to be modified.

fn execute2<F>(f:F, foo:&Foo, s:&String)
where
  F: Fn(&Foo, & String),
{
  f(foo,s);
}

execute2(Foo::method, & foo, & foo.s);//->method!


2022-09-30 13:57

There is another problem with the code you are asking, besides execute(foo.method, & foo.s).Let's fix it in order.

First, the argument for the execute function f:F, but

// Take only one & String as argument
    F: Fn(&String),

This is the Fn(&String) type.This is a closure that takes only one argument.

However, the method method in Foo has the following definition and takes two arguments:

impl Foo{
    // take two arguments: self: & Foo and s: & String
    fn method(&self,s:&String){

The method is of type Fn(&Foo,&String) and cannot be passed to the argument f (type Fn(&String) for the execute function.

Let's fix this first.

In the first place, Foo has the field s:String, so you do not need to take another s as an argument, such as fn method(&self, s:&String).Make the following changes:

before change

impl Foo{
    // take two arguments: self: & Foo and s: & String
    fn method(&self,s:&String){
        println!("{},s);
    }
}

modified

impl Foo{
    // Take only one self:&Foo argument
    US>fn method (&self) {
        // use fields s
        println!("{},self.s);
    }
}

The method is now of the Fn(&Foo) type with only one argument.

Then modify the execute function.Change the second argument s:&String to accept any type T.

fn execute<F,T>(f:F,t:&T)
where
    F: Fn(&T),
{
    f(t);
}

This allows you to take both the method of type Fn(&Foo) and the function of type Fn(&String) as arguments.

Finally, let's correct the code below that was originally an error.

execute(foo.method, & foo.s);

Rust's method is only one of the related functions. If foo is of type Foo, you write foo.method(), the compiler assumes that Foo::method(&foo).Therefore, you can write as follows.

 // Foo method as first argument and & Foo as second argument
execute(Foo::method, & foo);

You will now be able to compile.The results are as follows:

$cargo run
function!
method!

The overall code is as follows:

structure Foo{
    s —String,
}

impl Foo {
    US>fn method (&self) {
        println!("{},self.s);
    }
}

fn function(s:&String) {
    println!("{},s);
}

fn execute<F,T>(f:F,t:&T)
where
    F: Fn(&T),
{
    f(t)
}

US>fnmain(){
    lets=String::from("function!");
    execute(function, & s);
    // >> function!

    lets=String::from("method!");
    let foo=Foo{s};
    execute(Foo::method, & foo);
    // >> method!
}


2022-09-30 13:57

If you have any answers or tips


© 2023 OneMinuteCode. All rights reserved.