> Other languages are inconsistent? The answer is not to be inconsistent, and you can be consistent as a method or as a builtin function.
With dynamically typed languages, it is very hard to "be consistent as a method" since there are no tools to enforce that consistency. Social cues usually go 90% of the way, but not all the way whereas a function/generic method handles that just fine: to get a length, you call `len`. Period. The developer does not really have the option to do otherwise, unless he wants to opt out of the language's ecosystem.
Actually what I said above is not entirely true, there is one situation where it is "quite easy" to handle method consistency in a dynamically typed language: when you deal with mixins.
Because mixins have preconditions (methods and/or properties which need to exist for it to work), they enforce those names or they can't be used at all. And of course any method brought in by the mixin is "enforced" by default.
So is it with most things iteration in Ruby for instance: Enumerable mandates that a core internal iterator named `#each` exists (as well as #<=> optionally) and as a reward for doing so it gives about 30 methods "for free". That enforces consistency in collection traversal, because even if you reimplement some or all of these methods in the long term (for efficiency and whatnot) getting them "for free" out of the box is valuable.
Why then is len special? Should we also have builtins to add to a collection?
If it is good design there, should others repeat it? For example, if a module author is defining a new protocol for a set of objects that anyone can implement should they provide functions that delegate to the methods in their protocol?
For myself I think that the python community can be counted on to be consistent without the need for this duplication and indirection.
> Should we also have builtins to add to a collection?
No, because each collection type (mapping, sequence, set, ...) has very different addition semantics (and potentially arguments as well). On the other hand, there is a builtin to iterate over stuff.
With dynamically typed languages, it is very hard to "be consistent as a method" since there are no tools to enforce that consistency. Social cues usually go 90% of the way, but not all the way whereas a function/generic method handles that just fine: to get a length, you call `len`. Period. The developer does not really have the option to do otherwise, unless he wants to opt out of the language's ecosystem.
Actually what I said above is not entirely true, there is one situation where it is "quite easy" to handle method consistency in a dynamically typed language: when you deal with mixins.
Because mixins have preconditions (methods and/or properties which need to exist for it to work), they enforce those names or they can't be used at all. And of course any method brought in by the mixin is "enforced" by default.
So is it with most things iteration in Ruby for instance: Enumerable mandates that a core internal iterator named `#each` exists (as well as #<=> optionally) and as a reward for doing so it gives about 30 methods "for free". That enforces consistency in collection traversal, because even if you reimplement some or all of these methods in the long term (for efficiency and whatnot) getting them "for free" out of the box is valuable.