“What if” iterable.join()

…or “Let’s keep floging this dead horse”…

Over the weekend I got some reactions over the str.join() vs list.join(). Well, just for fun, this morning I played “what if” in my head.

So, let’s say every iterable got a join() method. So you could

>>> a = ['s', 'l', 'o', 'w']
>>> a.join('')
slow

Exactly as JavaScript does. Mkay. A could even be a tuple and would still work. Or, stupidly enough, a string and still work. But, then, what would be the first thing that would cross you mind when you saw this code for the first time:

>>> a = ['s', 'l', 'o', 'w']
>>> b = ['r', 'u', 'l', 'z']
>>> c = a.join(b)

You have a list in one side and a list in the other with a “join” method. List-join-list. Well, I’d expect another list with ['s', 'l', 'o', 'w', 'r', 'u', 'l', 'z'] which is what extend() does.

But let’s return to the original str.join(): What it does is, join the iterable in the parameters using “self”. Mkay, so what would be:

c = ['r', ['s', 'l', 'o', 'w'], 'u', ['s', 'l', 'o', 'w'], 'l', ['s', 'l', 'o', 'w'], 'z']

Which doesn’t make any sense.

Let’s go further. join() could, possible, call str() for the parameter and still react like JavaScript join(). Why? Well, as you may already know, Python have dynamic typing which means any variable can be used. Just to remember:

var l = ['s', 'l', 'o', 'w']
var j = l.join('')

would result in “slow” in JavaScript. Mkay, so

>>> l = ['s', 'l', 'o', 'w']
>>> r = ['r', 'u', 'l', 'z']
>>> j = l.join(r)

Would result in… guess what, "s['r', 'u', 'l', 'z']l['r', 'u', 'l', 'z']o['r', 'u', 'l', 'z']w" which, not surprisingly, still doesn’t make sense. Ok, if r was a simple string, it would react exactly like JavaScript. But it would be a mess with any other types. And what’s the point of dynamic typing if you force types?

So, str.join() not only makes code simpler and avoid some mess of monkey-patching, it also removes a greater problem: ambiguity.

And yes, I understand that JavaScript list.join(str) makes sense, but it still have the problem with “What about the other types? Are you a racist?”

Edit: Just for curiosity, I wrote a list.join(list) code in JavaScript to see the results. Here they are for you mind-bloggling pleasure:

js> var l = ['s', 'l', 'o', 'w'];
js> var r = ['r', 'u', 'l', 'z'];
js> var j = l.join(r);
js> j
sr,u,l,zlr,u,l,zor,u,l,zw

Python: why str.join() and not list.join()

or “Slowpoke finally understands Python

When I was in Australia, one guy kept asking why Python had the “horrible” (in his opinion) str.join() instead of obvious (in his opinion) list.join()?

After working with JavaScript for a while, I can understand his opinion: In JS, you have a list.join() of sorts and it makes a hell lot of sense.

But, then again, this morning it finally hit me: str.join() uses an iterable object as parameter, so any iterable object will work. For example:

>>> p = 'python'
>>> '-'.join(p)
'p-y-t-h-o-n'
>>>

Ok, this is understandable, but why not have a list.join() too? Well, this would mean that every iterable object would have to have a join() method (str.join(), tuple.join(), dict.join(), list.join() and all the new iterable objects that appeared in Python 3.0.) Since the C API for Python doesn’t allow object hierarchies (and all base types are implemented in C), the same method would have to be implemented over and over again. Not only that, but you would have several different ways to join() stuff instead of one, (now) obvious way.

Another way to fix this would monkey-patch every object to have a join() method, but that’s not the Python way. Monkey-patch is never the Python way.

And the same rule applies to len(): it takes any iterable due the same reason.