> As an argument type, Iterable is compatible with list, so it’s benefits are minimal (with rare exceptions).
Iterable is not compatible with list, but list is compatible with iterable. As the more general type, Iterable is better as an argument type unless you have a reason to force consumers to use lists. Even in private interfaces, I tend to prefer it, because I often end up wanting to pass something constructed on the fly, and creating an extra list for that rather than using a genexp just seems wasteful.
What I meant is argument marked as Iterable is compatible with list being passed.
> Iterable is better as an argument type unless you have a reason to force consumers to use lists
See, I feel the exact opposite: I use Iterable only if I have a reason to force consumers to use Iterable.
When you're marking argument as Iterable, how confident do you feel that you will never query collection size or access it by index?
I understand the desire to limit the interface and YAGNI, but since lists are more familiar and ubiquitous, using Iterable feels more complicated and unnecessarily pedantic.
> See, I feel the exact opposite: I use Iterable only if I have a reason to force consumers to use Iterable.
A broad argument type doesn’t force consumers not to use a narrower type. (It forces the implementer of the function to not rely on additional features of the narrower type, but if I am writing the function, I can be certain whether or not that is acceptable.)
Meanwhile, using a narrower type than needed for an argument does impose additional, unnecessary constraints on the consumer.
> When you're marking argument as Iterable, how confident do you feel that you will never query collection size or access it by index?
Absolute certainty, since I know what the function does and what I need to do it.
> I understand the desire to limit the interface and YAGNI, but since lists are more familiar and ubiquitous, using Iterable feels more complicated and unnecessarily pedantic.
Since all lists are Iterables but not all Iterables are lists, Iterables are necessarily more ubiquitous than lists.
> Since all lists are Iterables but not all Iterables are lists, Iterables are necessarily more ubiquitous than lists.
Yeah, that's what I meant by being pedantic :)
Here's a question: you receive a JSON payload that contains a list. You will then pass this list to two functions, one of them only iterates, another one uses list interface (let's say checks length among other things). Should you mark the argument as a list, or as an Iterable in the first function?
Solely from the code perspective, it's definitely an Iterable. But in my mental model it still remains a list. I don't like it when code deviates from my mental model. Forcibly treating it as an Iterable only makes it more complicated, while not giving anything in return.
Sure, you could say that callee should not have expectations of the caller, but what if those functions are already coupled? They are in the same module, and argument names clearly denote a collection. The fact that in certain scenarios it is "technically Iterable" serves nothing but pedantic value.
> Solely from the code perspective, it's definitely an Iterable. But in my mental model it still remains a list.
A list is an iterable with special additional features, so this is no conflict at all.
> I don't like it when code deviates from my mental model
But how is there a deviation; being an Iterable is part of being a list, not a deviation from it.
> Forcibly treating it as an Iterable only makes it more complicated, while not giving anything in return.
How is there anything “forcible”. Broader typing doesn’t “forcibly” impose anything. And it does give something, more freedom to callers.
> Sure, you could say that callee should not have expectations of the caller, but what if those functions are already coupled?
If there is coupling that exists for good cause and demands a list as the type of the data structure to be passes around, then, fine, use list. But usually Iterable or Sequence makes more sense; coding to interfaces which impose only what is actually required is better than to unnecessarily specific concrete types.
> But how is there a deviation; being an Iterable is part of being a list, not a deviation from it.
Because I'm a human, not a robot. If I can describe something with fewer words by sacrificing a little bit of accuracy, I might go for it when I don't deem that accuracy to be important.
If wife sends you to buy eggs, are you the type of person that buys caviar because "technically they're eggs"?
> coding to interfaces which impose only what is actually required is better than to unnecessarily specific concrete types
Iterable is not compatible with list, but list is compatible with iterable. As the more general type, Iterable is better as an argument type unless you have a reason to force consumers to use lists. Even in private interfaces, I tend to prefer it, because I often end up wanting to pass something constructed on the fly, and creating an extra list for that rather than using a genexp just seems wasteful.