On Tue, Jan 29, 2019, 12:22 AM Brendan Barnwell 

 What would you expect to happen with this line:
> ['foo', b'foo', 37, re.compile('foo')].join('_')

        That problem already exists with str.join though.  It's just currently spelled this way:

','.join(['foo', b'foo', 37, re.compile('foo')])

        . . . and the result is an error.  I don't see how it's semantically
any less sensible to call list.join on a list of non-string things than
it is to pass a list of non-string things to str.join.

This feels like an important asymmetry to me. There is a difference between to object itself being the wrong kind of thing and the arguments to a method being wrong.

In the first case, the object (a heterogenous list) can NEVER support a .join() method. It's simply the wrong kind of object. Of course, it's right as far as the basic type system goes, but its deeper (maybe "structural") type cannot support that method.

On the other hand, sure, almost any function, including methods, will choke on bad arguments. But no string *object* rules out joining if good arguments can be found.

I am sure readers will immediately reply, "what about list.sort()?" Unfortunately, that really will simply fail on lists of the wrong "type." After all these years, I still think that change in Python 2.3 or so was the wrong choice (for those with fewer gray hairs: when the hills were young, Python objects were arbitrarily comparable under inequality, even when the answer didn't "mean" anything).

I actually agree that a 'cast_to_string_and_join()' function sounds useful. Of course, you can write one easily enough, it doesn't need to be a method. For that matter, I think I'd probably rather that str.join() was simply a function in the string module or somewhere similar, with a signature like 'join(delim, iter_of_strings)'