What is the best syntax: `foo::<SomeMarker>(...)` or `foo(SomeMarker, ...)`

I have a trait that encapsulate a behavior, through associated functions.

pub trait Interface {
    fn bar(...);
}

struct BehaviorA;
impl Interface for BehaviorA { ... }
struct BehaviorB;
impl Interface for BehaviorB { ... }

I am implementing foo(), that receive the Interface as a compile time dependency injection to be able to specialize it's behavior.

What syntax should I prefer?

fn foo<T: Interface>(...) {
    T::bar(...)
}
// Now we can select at compile time witch behavior to use for foo()
fn main() {
    foo::<BehaviorA>(...); // called using turbofish
}

or

fn foo<T: Interface>(_:T, ...) {
    T::bar(...);
}

fn main() {
    foo(T, ...); // called by creating an instance of the zero-sized struct
}

To give an example of use of this pattern, Interface could be TextFormatter, which has associated functions like bold() and strike(). Then you have a MarkdownFormatter, HtmlFormatter and a AnsiFormatter that implements TextFormatter. Finally foo() just need a TextFormatter, and will delegate the formatting to it.

I think if the difference is between the types, then it makes more sense to associate the function with only the type, without needing an instance of it. (In fact you might as well go ahead and make it a variantless enum instead of a struct.)

1 Like

enum BehaviorA is better than struct BehaviorA? I don't see what does this change.

Not much, at this point it's a purely stylistic question. If you have an enum without variants, you can't instantiate it, so it's immediately clear to the user that it's only supposed to be used at the type level.

It make sense. Thanks.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.