HashMap<_, Box> - why does this feel wrong?

⚓ Rust    📅 2026-06-28    👤 surdeus    👁️ 1      

surdeus

Other than "you're writing python in rust" - which I absolutely am as far as the inspiration for this pattern is concerned - why does this feel wrong?

I have a situation where I need to call some, or all, of a series of calculations based upon the contents of an "optional iterator of requests".

I initially got frustrated and concerned about duplicating all those calcs in the Some(requests) & None (= do all calcs) arms, so created named closures for each.

Then I got frustrated and concerned about a having both a long if ... if else ... else chain and a listing of calls to all closures.

Now I have:

let mut available_methods: HashMap<Ident, Box<dyn Fn() -> TokenStream2>> = HashMap::new();
available_methods.insert(
    ...
);
...
match attribute.meta {
    syn::Meta::Path(_) => {
        for method in available_methods.values() {
            methods.extend(method())
        }
    }
    syn::Meta::List(_) => {
        let wanted: Punctuated<Ident, Token![,]> =
            attribute.parse_args_with(Punctuated::parse_terminated)?;

        for method in wanted {
            match available_methods.get(&method) {
                Some(method) => methods.extend(method()),
                None => todo!("error for unknown names"),
            };
        }
    }
    syn::Meta::NameValue(_) => todo!("can't process name value"),
};
...

The concerns I can otherwise think of all fall into "if you find yourself here ... you've done something a bit nasty":

  • effectively a stringly-typed API (yep - that's forced onto me, not chosen)
  • an optional parameter for requested calcs (yep - that's partially forced onto me, and partially chosen as better than an arbitrary value "all" in a stringly-typed API)

But still ... this feels like a bad smell that I can't quite put my finger on. Is it obvious to anyone else?

3 posts - 3 participants

Read full topic

🏷️ Rust_feed