News for hackers. Stuff that matters.
Re:Examples of Incorrect Abstractions in Other Languages by mokus on Tuesday May 19, 2020 @07:38PM (#23241625)
I agree with your overall point, but regarding your “could you design....” rhetorical: in that example, isn’t it already inspecting the type of the list elements and then doing a specific different thing (printing that message) if it happens to be a list of strings? Why not just go one step further and just do the thing instead of nag the user to do the thing?
Re:Examples of Incorrect Abstractions in Other Languages by andolanra on Tuesday May 19, 2020 @08:00PM (#23241798)
Because Python's design philosophy is that, for a given operation exposed by the language, there should ideally be a single clear way of doing it, and that philosophy is optimized around reading code rather than writing it. You might need to do a few more edits while you're writing the code, sure, but now a reader of your code will always find sum for numbers and join for strings without even having to examine the context of the code in question.

I'm not saying that's necessarily the correct design approach, but it's the one that Python has explicitly established as their guiding principle! A different language will take a different approach: Ruby, for example, likes to build multiple alternative ways of accomplishing the same thing, which leads to multiple aliases for built-in methods or various alternative flags that allow a method to behave in a number of ways. It shouldn't be a surprise that Ruby is fine with the equivalent operation:

    irb(main):001:0> ["a", "b"].sum(identity="")
    => "ab"
But that's because Ruby's design sensibility is different from Python's. You might like one better than another, but they both come from a consistent vision of how to design programming languages.
Re:Examples of Incorrect Abstractions in Other Languages by saagarjha on Tuesday May 19, 2020 @08:16PM (#23241930)
> Because Python's design philosophy is that, for a given operation exposed by the language, there should ideally be a single clear way of doing it

This philosophy falls apart immediately once you start using Python though. I have yet to see it actually be used for anything but not implementing features that someone wants.

Re:Examples of Incorrect Abstractions in Other Languages by canjobear on Wednesday May 20, 2020 @01:27AM (#23243557)
What other languages are you comparing against? I came to Python from Perl and the one-way-to-do-it-ness was noticeable and refreshing.
Re:Examples of Incorrect Abstractions in Other Languages by saagarjha on Wednesday May 20, 2020 @10:12PM (#23254207)
I don't think many other languages make that claim, and I think it's generally an anti-goal in diverse multiparadigm languages. I don't even understand why Python tries to have it: I can think of three fairly idiomatic ways to sum a list of numbers right off the top of my head; it's immediately clear that such a proposition is not feasible for the language. The only time I have heard it come up is when there is an unsaid accusation that the language is getting "to complex" and someone wants to block the addition of a feature…
Re:Examples of Incorrect Abstractions in Other Languages by oh_sigh on Tuesday May 19, 2020 @11:13PM (#23242948)
But in almost all of the langauge, TOOWTDI is not strictly enforced, it is merely a highly encouraged convention. For example, why am I allowed to do

    mylist = [x*2 for x in range(1,10)]
but also do

    mylist = []
    for x in range(1,10):
      mylist.append(x*2)
That's two ways to do the same thing, and I bet you would find a lot of the latter in beginner's python code. I think a better choice would to just have a linter which enforced the correct usage of sum() and join(), and not the implementation itself.
Re:Examples of Incorrect Abstractions in Other Languages by lgas on Wednesday May 20, 2020 @12:08AM (#23243206)
There's probably a lot more than two ways too, eg.

    mylist = map(lambda x: x * 2, range(1, 10))
Re:Examples of Incorrect Abstractions in Other Languages by fractalb on Wednesday May 20, 2020 @02:53AM (#23244022)
map will return an iterator, not a list
Re:Examples of Incorrect Abstractions in Other Languages by kortilla on Wednesday May 20, 2020 @03:44AM (#23244339)
Then call list(map(...

The point stands.

Re:Examples of Incorrect Abstractions in Other Languages by kragen on Wednesday May 20, 2020 @05:21AM (#23244862)
Only in Python 3, not Python 1 or Python 2.
Re:Examples of Incorrect Abstractions in Other Languages by hawski on Wednesday May 20, 2020 @08:59AM (#23246317)
Let's concatenate strings.

  a + b
  f"{a}{b}"
  "".join([a, b])
  "{}{}".format(a, b)
If a == b, then you can also, which itself is a bit ridiculous:

  a * 2
Is mentioning StringIO considered cheating?

I would feel the Zen if Python would have a separate concatenation operator, it could be even the same for strings and lists. Lack of the operator in popular languages is my pet peeve.

Re:Examples of Incorrect Abstractions in Other Languages by Izkata on Wednesday May 20, 2020 @05:22PM (#23251952)
You forgot:

  "%s%s" % (a, b)
(Still works at least as of python 3.6)
Re:Examples of Incorrect Abstractions in Other Languages by nitrogen on Wednesday May 20, 2020 @01:14AM (#23243499)
Unless something has changed recently in Ruby, won't identity="" as a parameter just assign the empty string to a variable named identity and then pass the empty string as an unnamed positional parameter?
Re:Examples of Incorrect Abstractions in Other Languages by DougBTX on Wednesday May 20, 2020 @06:32AM (#23245270)
You're right, it should be:

    ["a", "b"].sum("")
Re:Examples of Incorrect Abstractions in Other Languages by skybrian on Tuesday May 19, 2020 @08:53PM (#23242187)
One reason is that using "sum" versus "join" helps the reader understand which operation is being performed. You can tell whether the author was expecting a list of strings or a list of numbers. This hint about the author's intent also helps the compiler or runtime generate better error messages.

As a reader, you don't know what an abstract operation does, just that it should obey certain rules. Writing code abstractly when abstraction is unnecessary removes information, which has a cost in readability.

Now if you want to write abstract code then it will be frustrating, but some languages are optimized for writing concrete code.

At least, in this particular case. I'm not sure how consistent Python is about this.

Re:Examples of Incorrect Abstractions in Other Languages by gugagore on Wednesday May 20, 2020 @01:15AM (#23243505)
This reason doesn't make sense to me, because of `+`. If I do `a + b`, you don't know if my intent is to add numbers, join strings, or concatenate lists. If `sum` and `join` are supposed to look different to convey intent, then the binary operators should look different as well.
Re:Examples of Incorrect Abstractions in Other Languages by stouset on Thursday May 21, 2020 @04:12PM (#23264402)
The argument against operator overloading doesn't hold water with me at all.

If 3 + 2 is allowed but you don't think "a" + "b" should work, why should 8.1 + 1.9 work? If your argument is that it's because they're numbers, what about a Complex library, or numeric vectors, or GMP? If I can do 3 + 2 and 8.1 + 1.9, I should be allowed to make Complex{0, 1} + Complex{4, 9} work, or Vector{1, 0} + Vector{2, 2}, or BigInt{99999...} + BigInt{9999...}.

I can sort of see the argument in dynamically-typed languages when you might not know what the operands are ahead of time, but for statically-typed languages like Rust and Go (Rust gets this very, very right FWIW)? There's no defensible argument against it. Why is `+` magic and holy, but a `fn add(...)` isn't?

Re:Examples of Incorrect Abstractions in Other Languages by edflsafoiewq on Wednesday May 20, 2020 @12:15AM (#23243236)
That would very greatly increase the complexity of sum. Consider that python is dynamically typed, has heterogeneous lists, and that sum takes an iterable, not just a list.

> isn’t it already inspecting the type of the list elements

Actually it only checks if the type of start (the initial accumulator value) is a string. If the accumulator becomes a string later on, it's happy to sum strings.

Re:Examples of Incorrect Abstractions in Other Languages by tom_mellior on Wednesday May 20, 2020 @02:24AM (#23243857)
If that check is there anyway, and the preferred path is known, I would think that the great increase in complexity would look something like this:

     if trying_to_sum_strings(args):
    -    complain_bitterly()
    +    separator.join(args)
Re:Examples of Incorrect Abstractions in Other Languages by edflsafoiewq on Wednesday May 20, 2020 @04:13AM (#23244512)
Like I said, the current check for trying_to_sum_strings is just that start is a string. So if you would do this you would actually make sum less consistent, since sum([x], ''), which should logically be '' + x, would become ''.join([x]), which not the same (think of an example with __radd__).
Re:Examples of Incorrect Abstractions in Other Languages by tom_mellior on Wednesday May 20, 2020 @04:34AM (#23244639)
I don't follow. In your example, if x is a string, there is no problem since '' + x is just x. If x is not a string, the new path would not trigger, so the behavior would be as before.

EDIT: OK, I think if the example is sum([some_string, some_not_string], '') then there is a possibility that some_string + some_not_string might be a valid expression computing a value while ''.join([some_string, some_not_string]) would complain that some_not_string is not a string.

Re:Examples of Incorrect Abstractions in Other Languages by fractalb on Wednesday May 20, 2020 @03:34AM (#23244277)
> Why not just go one step further and just do the thing instead of nag the user to do the thing?

At least, readability suffers.

"".join(["a", "b"]) is a lot more intuitive than sum(["a", "b"], start="")

edit: A beautiful abstraction is the one that feels as good when it's read as when it's written.

Re:Examples of Incorrect Abstractions in Other Languages by lmm on Wednesday May 20, 2020 @05:52AM (#23245037)
> "".join(["a", "b"]) is a lot more intuitive than sum(["a", "b"], start="")

No it isn't. The join method being on the separator string is a Pythonism that looks crazy coming from any other language.

Re:Examples of Incorrect Abstractions in Other Languages by theelous3 on Wednesday May 20, 2020 @07:34AM (#23245646)
The point they are making is that

    join(xs, "")
    xs.join("")
or whatever else you want to come up with is more readable than building more string stuff in to sum, not that having join be a str method is the best way.
Re:Examples of Incorrect Abstractions in Other Languages by CJefferson on Wednesday May 20, 2020 @04:19AM (#23244550)
Lits of maths based languages do [1,2] + [3,4] = [4,6], now you really need a different join operator.
Re:Examples of Incorrect Abstractions in Other Languages by karatestomp on Tuesday May 19, 2020 @07:56PM (#23241771)
Sum and join mean different things. If sum didn't fail on chars I'd expect it instead to sum their binary values, which is a thing one occasionally actually does want to do, not to join/concatenate them. If it can't do that (or you have strings, as in this case, for which it makes less sense—the most sensible thing there would probably be to treat it as a byte array and do something with that, though any conceivable use of that probably breaks down with UTFs 8 or 16 instead of ascii) I'd want it to fail.
Re:Examples of Incorrect Abstractions in Other Languages by tom_mellior on Wednesday May 20, 2020 @02:27AM (#23243873)
Sum is the iteration of +. + on strings is concatenation. If you expected otherwise from sum, it's your expectations that might be wrong. What even is a Python string's "binary value"? Also, Python has no chars.
Re:Examples of Incorrect Abstractions in Other Languages by uryga on Wednesday May 20, 2020 @07:01AM (#23245438)
so you'd expect this behavior?

  sum("abc") =
  sum(ord(c) for c in "abc") =
  sum([97, 98, 99]) =
  294
because wow, i... can't think of why you'd ever actually want that. (though it'd be perfectly natural for byte arrays)
Re:Examples of Incorrect Abstractions in Other Languages by stouset on Thursday May 21, 2020 @05:12PM (#23265403)
Byte arrays sure. Not strings. This is why having clear types is important! Strings aren't just byte arrays. Characters aren't just bytes.
Re:Examples of Incorrect Abstractions in Other Languages by Veedrac on Wednesday May 20, 2020 @08:54AM (#23246278)
Magic has the unfortunate downside of preventing people comprehending what's happening. This isn't an issue exclusive to str, and having it silently autocorrect for only that one case will teach people the wrong thing.