6 ms·
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 element
by mokus 6y ago
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?
- karatestomp 6y agoSum 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.
- tom_mellior 6y agoSum 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.
- uryga 6y agoso 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)
- stouset 6y agoByte arrays sure. Not strings. This is why having clear types is important! Strings aren't just byte arrays. Characters aren't just bytes.
- andolanra 6y agoBecause 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.
- saagarjha 6y ago> 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.
- canjobear 6y agoWhat other languages are you comparing against? I came to Python from Perl and the one-way-to-do-it-ness was noticeable and refreshing.
- saagarjha 6y agoI 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…
- skybrian 6y agoOne 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.
- gugagore 6y agoThis 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.
- stouset 6y agoThe 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?
- edflsafoiewq 6y agoThat 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.
- tom_mellior 6y agoIf 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)
- edflsafoiewq 6y agoLike 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__).
- tom_mellior 6y agoI 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.
- fractalb 6y ago> 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.
- deleted 6y ago[deleted]
- lmm 6y ago> "".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.
- theelous3 6y agoThe 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.
- CJefferson 6y agoLits of maths based languages do [1,2] + [3,4] = [4,6], now you really need a different join operator.
- Veedrac 6y agoMagic 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.