Idiomatic return for APIs with arrays

I was wondering what the consensus, or idiomatic way of designing (non-web) APIs where data is returned that can either be a list of items or a single item of the same type.

For example, assume I have an API method pub fn foo() -> Vec<Bar>;. More often than not I see an additional method pub fn foo_single(id: Id) -> Bar; that just returns a single item from the vector based on either a field or a predicate.

With rust and lazy evaluation of iterators I don't really see the point in this because the user could just use filter. Exception: Filtering does some internal stuff that shouldn't be exposed to the caller.

Opinions?

With the functionality you've described, a caller who just wants one Bar, but no foo_single:

  • Unnecessary allocation of a Vec is required
  • Unnecessary cloning/copying/generation/whatever of every extra Bar is required
  • The caller also has to do more work too
    • Know how to go from Id to Vec[?]
    • Do so without any advantages inherent in the original data structure[1]
    • Move stuff out of the Vec and discard the rest

Doing work lazily is still doing work. With a Vec, you may have an index you can utilize, but that's not iteration.

Imagine a hash map that gave you a Vec<(&Key, &Value)> instead of being able to get a particular entry. Or without Vec, still having to iterate over potentially every other entry, comparing keys as you go.


  1. unless the Vec has those same advantages ↩ī¸Ž

2 Likes

If your list is always going to be a sequence (like Vec<T>), maybe return impl Iterator<Item = Bar> instead. That way you let the caller decide if they want to either collect() into a vector or just .next().unwrap() for the first element.

1 Like