How do I pass static functions as parameters

Viewed 53

What I am trying to do is to implement a strategy pattern in Rust. In this example I have several sorting algos that I've coded:

use std::cmp::{ Ord, Ordering };

pub trait Sorter {
    fn sort<T>(arr: &mut Vec<T>, desc: bool) where T: Ord + Copy;
}

pub struct BubleSort;
pub struct SelectionSort;

impl Sorter for BubleSort {
    fn sort<T>(arr: &mut Vec<T>, desc: bool) where T: Ord + Copy{
        ...
    }
} 

impl Sorter for SelectionSort {
    fn sort<T>(arr: &mut Vec<T>, desc: bool) where T: Ord + Copy{
       ...
    }
}

Then I want to pass one of them to a function to use it. Something like this:

fn sort<T>(sorter: dyn Sorter, arr: &mut Vec<T>) {
    sorter::sort(arr);
}

Also is it possible to add them in lets say a Vec and iterate over it, so I can call the functions from there?

Is this possible, or do I need to make instances of the structs and use methods instead?

1 Answers

You can statically parameterise on the sorter type:

fn sort<Strategy: Sorter, T>(arr: &mut Vec<T>, descending: bool) where T: Ord + Copy {
    Strategy::sort(arr, descending);
}

fn main() {
    let mut v: Vec<u8> = Vec::new();
    sort::<SelectionSort, _>(&mut v, false);
}

In other situations you might want to instantiate the structure and work with instance methods, but since the method is generic it can't be dynamically dispatched, therefore it's not super useful. Although I guess you could have an intermediate enum serving as dynamic dispatcher:

fn sort<Strategy: Sorter, T>(strategy: Strategy, arr: &mut Vec<T>, descending: bool) where T: Ord + Copy {
    strategy.sort(arr, descending);
}

enum Dynamic {
    BubbleSort,
    SelectionSort
}
impl Sorter for Dynamic {
    fn sort<T>(&self, arr: &mut Vec<T>, desc: bool) where T: Ord + Copy {
        match self {
            Self::BubbleSort => sort(BubbleSort, arr, desc),
            Self::SelectionSort => sort(SelectionSort, arr, desc),
        }
    }
}

fn main() {
    let mut v: Vec<u8> = Vec::new();
    sort(Dynamic::BubbleSort, &mut v, false);
}
Related