#Passing function as an argument

8 messages · Page 1 of 1 (latest)

fluid topaz
#

This code asserts the json data from a discord repo to a function i wrote, to see if results match based on input. How do I pass a function as an argument so i can test the function with just a url and function as arguments?

use serde::{Serialize, Deserialize};

#[derive(Debug, Serialize, Deserialize)]
struct Test<A, R> {
    args: Vec<A>,
    #[serde(rename = "return")]
    result: R
    
}
#[tokio::main]
async fn main() {
    run_test().await.unwrap()
}


async fn run_test() -> Result<(), reqwest::Error> {
    let tests: Vec<Test<String, f64>> = reqwest::Client::new()
        .get("https://raw.githubusercontent.com/beginner-codes/challenges/main/weekday/test_cases_622.json")
        .send()
        .await?
        .json()
        .await?;

    for test in tests.iter() {
        assert!(test.result == shortest_distance(&test.args[0]));
        println!("{}",test.result)
    }

    println!("TEST PASSED");
    Ok(())
}

fn shortest_distance(points: &str) -> f64 {
    let p = points.split(",").map(|point| point.parse::<f64>().unwrap()).collect::<Vec<_>>();
    return format!("{:.2}",f64::sqrt((f64::powi((p[2]) - (p[0]), 2)) + (f64::powi((p[3]) - (p[1]), 2) ))).parse().unwrap(); 
}

heady moon
#

Do you want to pass the function as an argument though, or do you mean you want to be able to test the behaviour of the run_test function?

Since it's an async function, calling it in main there will create the future, but nothing is actually progressing, or executing the future which is why calling run_test is not doing anything for you

fluid topaz
fluid topaz
heady moon
#

There's a set of traits that Rust implements for closures and functions: Fn, FnMut, and FnOnce so you can pass a function by passing some type that implements one of these - depending on the properties you want from the function that you're accepting

#

?play

fn call_callback(f: impl Fn(&str)) {
    // can be called multiple times
    f("1");
    f("2");
}

fn call_callback_mut(mut f: impl FnMut(&str)) {
    // can be called multiple times
    f("3");
    f("4");
}

fn call_callback_once(f: impl FnOnce(&str)) {
    f("5");
    // f("6"); // this would error because function can only be called once (it owns the environment).
}

fn call_callback_with_return_val(f: impl Fn(&str) -> u8) -> u8 {
    f("6")
}

fn main() {
    // Fn trait represents functions that borrow from their environment
    // but immutably.
    call_callback(|string| {
        println!("non-mutable => {}", string.parse::<u8>().unwrap());
    });
    
    // FnMut trait represents functions that borrow from their environment
    // mutably so we can modify "vec" here in the callback.
    let mut vec = Vec::new();
    call_callback_mut(|string| {
        let num = string.parse::<u8>().unwrap();
        vec.push(num); // wouldn't be possible in a Fn closure
        println!("mutable => {:?}", vec);
    });
    
    // FnOnce trait represents functions that own their environment and consume
    // it, so can only be run once.
    call_callback_once(|string| {
        let num = string.parse::<u8>().unwrap();
        vec.push(num); // wouldn't be possible in a Fn closure
        println!("owned => {:?}", vec);
    });
    
    // Can have the callback function return a value too.
    println!("with return => {}", call_callback_with_return_val(|string| {
        string.parse::<u8>().unwrap()
    }));
}
vast iceBOT
#
     Running `target/debug/playground`

non-mutable => 1
non-mutable => 2
mutable => [3]
mutable => [3, 4]
owned => [3, 4, 5]
with return => 6
heady moon
#

I was trying to find the appropriate section in the book for these traits but couldn't - the essential differences are:

Fn is used for functions that can be called multiple times but borrow their environment only immutably
FnMut is used for functions that can be called multiple times but borrow their environment mutably
FnMut is a function that can only be called once because it owns and consumes the environment

They're analagous to &self, &mut self, and self on member functions