When do you choose to type a given function’s return type as Seq vs Iterable vs Traversable (or alternatively even deeper within Seq‘s hierarchy)?
How do you make that decision? We have a lot of code that returns Seqs by default (usually starting from results of a DB query and successive transformations). I tend to want to make the return types Traversable by default and Seq when specifically expecting a given order. But I don’t have a strong justification for doing so.
I am perfectly familiar with the definition of each trait, so please don’t answer with defining the terms.
This is a good question. You have to balance two concerns:
Where (1) asks you to be as little specific about the type (e.g.
IterableoverSeq), and (2) asks you the opposite.Even if the return type is just
Iterable, you can still return let’s say aVector, so if the caller wishes to gain extra power, it can just call.toSeqor.toIndexedSeqon it, and that operation is cheap for aVector.As a measure of the balance, I would add a third point:
Seq. If you can assume that no two equal objects can occur, give aSet. Etc.Here are my rules of thumb:
Set,Map,Seq,IndexedSeqListin favour ofSeq. It allows the caller to do pattern matching with the cons extractorscollection.immutable.Set,collection.immutable.IndexedSeq)Vector), but the general type (IndexedSeq) which gives the same APIIteratorinstances, the caller can then easily generate a strict structure, e.g. by callingtoListon itIndexedSeqOf course, this is my personal choice, but I hope it sounds sane.