News for hackers. Stuff that matters.
Re:Examples of Incorrect Abstractions in Other Languages by andolanra on Tuesday May 19, 2020 @07:30PM (#23241567)
Some of these are arguably "incorrect abstractions", but others are just design decisions that are being treated as "incorrect" because they don't follow Haskell's design sensibilities. A perfect example is the complaint about sum in Python:

   >>> sum(["a", "b"], start="")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: sum() can't sum strings [use ''.join(seq) instead]
I don't think this is incorrect at all! There's a very good reason to use join instead of sum for adding strings together: join is a lot more efficient than simply adding strings together, because it will precompute the amount of space needed for the resulting string at once and then put all the strings into the buffer at once, whereas using sum in the naïve way suggested would do a different append for each element. These are just different tools for different purposes!

Could you design a sum that automatically looked at its argument type and deferred to join for strings? Sure! And that'd be a valid design decision as well. But the specific choice Python made here is motivated and defensible: it's only "incorrect" if your personal definition of "correct" is "built with the same algebraic sensibility that Haskell's designers had," but at that point, all other languages are "incorrect" because they're not Haskell!

Re:Examples of Incorrect Abstractions in Other Languages by naasking on Wednesday May 20, 2020 @08:02AM (#23245828)
> I don't think this is incorrect at all! There's a very good reason to use join instead of sum for adding strings together: join is a lot more efficient than simply adding strings together, because it will precompute the amount of space needed for the resulting string at once and then put all the strings into the buffer at once, whereas using sum in the naïve way suggested would do a different append for each element.

Differing performance characteristics should not break the semantics of an abstraction. That's an abstraction leak which prevents writing generalized abstractions.

Re:Examples of Incorrect Abstractions in Other Languages by tines on Wednesday May 20, 2020 @01:46AM (#23243641)
Special cases like this make generic code very hard to write. If I'm writing a library that needs to handle user-provided data agnostic of type and I want to do a sum operation, now I have to add checks all over the place for whatever special cases python has.
Re:Examples of Incorrect Abstractions in Other Languages by wirrbel on Wednesday May 20, 2020 @03:12AM (#23244143)
I think never have I written generic code for summing up numbers AND concatenating strings. Even the Haskell people would agree I think. So the design problem is in overloading `+` for string and list concatenation in Python in the first place.

But I guess in terms of strings let's take a moment and remember the one truly good design decision that Python devs made about strings (which isn't usual for an imperative language). Strings are immutable by default.

Re:Examples of Incorrect Abstractions in Other Languages by lmm on Wednesday May 20, 2020 @05:51AM (#23245024)
> I think never have I written generic code for summing up numbers AND concatenating strings. Even the Haskell people would agree I think.

Erm, Haskell people write code that can do this all the time - you write stuff in terms of generic monoid and then it just does. I can even think of a concrete case where I used those two examples: I had essentially a report that looped over a bunch of rows and accumulated something as a secondary effect, and in one client's case that was a string explaining what had happened, and in another client's case that was a count of how many things had been processed.

Re:Examples of Incorrect Abstractions in Other Languages by still_grokking on Wednesday May 20, 2020 @08:33AM (#23246117)
So you've written (of course type safe) generic code that was in principle able to achieve the same effect as described in https://stackoverflow.com/questions/9032856/what-is-the-expl... ? ;-)

Batman!

Re:Examples of Incorrect Abstractions in Other Languages by rowanG077 on Wednesday May 20, 2020 @08:56AM (#23246294)
No. He was talking about monoids. The content in the link you are talking about aren't monoids.
Re:Examples of Incorrect Abstractions in Other Languages by still_grokking on Wednesday May 20, 2020 @09:17AM (#23246459)
Do the implementation details matter if you could achieve the same result?
Re:Examples of Incorrect Abstractions in Other Languages by rowanG077 on Wednesday May 20, 2020 @10:01AM (#23246855)
It's not about the implementation details. It's about that the things that are mentioned in the link make no logical sense. The addition operator allows values of different types to be added together and even worse the resulting values type isn't required to have the type of either operands.

It's not possible to write the generic code since there are basically no constraints. Generic code is all about constructs with certain invariants and use those invariants to create something new. Javascript addition basically has no invariants.

Re:Examples of Incorrect Abstractions in Other Languages by still_grokking on Wednesday May 20, 2020 @12:01PM (#23248449)
>It's not about the implementation details. It's about that the things that are mentioned in the link make no logical sense. The addition operator allows values of different types to be added together and even worse the resulting values type isn't required to have the type of either operands.

I would argue that that's not true.

JS is a "mono-typed" language and there is therefore only one type of things you can operate on and return as a result.

>It's not possible to write the generic code since there are basically no constraints. Generic code is all about constructs with certain invariants and use those invariants to create something new. Javascript addition basically has no invariants.

That's backwards to my point. I tried to point out that having generic code which can operate on (almost) arbitrary data structures mixing for example natural numbers or lists of arbitrary things will lead in the end to the same puzzling results as the "classical JS-Batman" example.

Don't get me wrong, generics are a great tool! But imho it's easy to "overstretch" their usage until a point where things become "so generic" that your functions can operate on "almost everything" but the results become as surprising as the alleged "JS insanities".

Something like the Monoid abstraction is incredibly powerful (most languages can't express such an abstraction in a sensible way even). Using such a powerful tool to abstract over some very concrete and banal things (that would be handled better separately as they're "not the same", no matter there may be a deep mathematical connection) is not a good architecture imo. If your code handling "concrete things" is written in a very generic and abstract way you won't have any "normal" tools left on your belt in case you would need to abstract over that stuff you've just written (at this point you could enter type-level programming or something that will achieve something similar but you will than end up with laughable complex code to handle in the end banal business logic).

https://en.wikipedia.org/wiki/Rule_of_least_power

Re:Examples of Incorrect Abstractions in Other Languages by lmm on Thursday May 21, 2020 @09:33AM (#23258084)
> JS is a "mono-typed" language and there is therefore only one type of things you can operate on and return as a result.

Well, in that case programmers should not be surprised when they subtract an integer from a string and get NaN. Apparently they are are surprised though. I'd prefer my language not let me subtract an integer from a string, since if I ever attempt to subtract an integer from a string that's almost certainly an error.

> That's backwards to my point. I tried to point out that having generic code which can operate on (almost) arbitrary data structures mixing for example natural numbers or lists of arbitrary things will lead in the end to the same puzzling results as the "classical JS-Batman" example.

But that's not true. Nothing you do with a monoid will create such a puzzling result, because summing a list via a monoid is - by definition - equivalent to summing it by calling + pairwise. (Of course, if you have a type for which + behaves in a confusing way, then this might be confusing - but it's not the monoid that's being confusing there).

If you want to claim monoid-based code can be confusing, try using some actual examples of monoid-based code, rather than code in a different language that isn't using monoids and wouldn't compile if it did.

> If your code handling "concrete things" is written in a very generic and abstract way you won't have any "normal" tools left on your belt in case you would need to abstract over that stuff you've just written (at this point you could enter type-level programming or something that will achieve something similar but you will than end up with laughable complex code to handle in the end banal business logic).

This is completely wrong. If you write your code generically it becomes easier to abstract over, not harder. For example, if you write a sort function that operates generically from lists and separate that from your comparison function instead of writing separate functions for sorting lists of integers and lists of strings, it's much easier to then make further abstractions over your sorting.

> https://en.wikipedia.org/wiki/Rule_of_least_power

Again you're getting it backwards. Code written in terms of monoids is less powerful than code written in terms of a specific datatype, which means there are far fewer ways to get it wrong.

Re:Examples of Incorrect Abstractions in Other Languages by rowanG077 on Wednesday May 20, 2020 @02:47PM (#23250325)
> JS is a "mono-typed" language and there is therefore only one type of things you can operate on and return as a result.

Javascript has a type system that is enforced at run-time.

> That's backwards to my point. I tried to point out that having generic code which can operate on (almost) arbitrary data structures mixing for example natural numbers or lists of arbitrary things will lead in the end to the same puzzling results as the "classical JS-Batman" example.

I don't agree. The entire point of the link you posted was the insanity of the semantic of the addition operations in Javascript. Monoids are very simple and well defined. The javascript insanity would need pages upon pages of explanations because basically everything is a special case. In contrast monoids can be fully explained in a two sentences.

Re:Examples of Incorrect Abstractions in Other Languages by still_grokking on Wednesday May 20, 2020 @06:59PM (#23253007)
>> JS is a "mono-typed" language and there is therefore only one type of things you can operate on and return as a result.

>Javascript has a type system that is enforced at run-time.

Nobody questions that JS has "runtime type-checks". But that's irrelevant to my point. I've referenced of course this here:

https://existentialtype.wordpress.com/2011/03/19/dynamic-lan...

>Monoids are very simple and well defined.

Sure. Just define an instance for a type that models a JS runtime-object, let's see what happens… ;-)

But I see, my point is still not explained well: What I'm trying to say is that using abstractions that are so powerful that the resulting code can operate on (almost) arbitrary "unrelated" things using that code will lead to the same kind of puzzling outcomes as "JS Watman".

(And like I said, a deep mathematical relation doesn't make things "related" in a practical sense automatically. For example when it comes to "correct" domain modeling of business cases where you explicitly want to treat different parts of your system separately; as this results in a less "entangled" architecture. Gluing together parts that are unrelated through clever code on the other hands side creates maintenance hell where everything depends on everything, but you can't even see what depends on what as everything is generic; that's the opposite of good software engineering, imho. To throw a few phrases: "Divide and conquer!" "Use the right tool for the job!" "Use the least powerful tool that gets the job done well!").

Re:Examples of Incorrect Abstractions in Other Languages by Avi-D-coder on Wednesday May 20, 2020 @04:44AM (#23244698)
We don't just write generics over types of strings ([Char], Text, etc..) we write over Semigroups and Monoids. Concatenation with <> is standard practice.
Re:Examples of Incorrect Abstractions in Other Languages by noelwelsh on Wednesday May 20, 2020 @04:36AM (#23244651)
It's very common in data processing to sum up stuff (e.g. unique visitors, total visitors, total revenue, etc.) To handle this you typically want to write a generic library that makes summing up stuff easy. I can't think of an example where you'd want to add up strings (more likely lists of strings) but it is definitely the case for other data structures (sets, vectors, lists, numbers, etc.)
Re:Examples of Incorrect Abstractions in Other Languages by kragen on Wednesday May 20, 2020 @05:19AM (#23244852)
Python sum() can handle summing up other data structures, although, as with foldl, you may have to give it an initial accumulator argument:

    >>> import numpy as np
    >>> xs = np.arange(9).reshape((3,3))
    >>> xs
    array([[0, 1, 2],
           [3, 4, 5],
           [6, 7, 8]])
    >>> sum(xs)  # builtin sum, not numpy sum
    array([ 9, 12, 15])
    >>> sum([[3, 11], [5]], [])
    [3, 11, 5]
    >>> sum([(3, 11), (5,)], ())
    (3, 11, 5)
However, that doesn't work for strings; there's a special-case check for that.
Re:Examples of Incorrect Abstractions in Other Languages by tgv on Wednesday May 20, 2020 @02:43AM (#23243962)
There's no language in which you would be able to write a function for arbitrary data structures using sum(), and get a reasonable outcome.

The problem with Python is that it doesn't have typing that can express "I can sum".

Re:Examples of Incorrect Abstractions in Other Languages by anentropic on Wednesday May 20, 2020 @05:44AM (#23244981)
Actually, I believe this is expressible in Python's type system:

    # Python 3.8
    from typing import Protocol, TypeVar

    T = TypeVar('T')

    class Summable(Protocol[T]):
        def __add__(self, other: T) -> T: ...

In Python 3.4-3.7 you'd need to install typing-extensions library:

    from typing_extensions import Protocol
Re:Examples of Incorrect Abstractions in Other Languages by still_grokking on Wednesday May 20, 2020 @09:28AM (#23246551)
Interesting. It seems that "every second language" gets "type-classes" these days…

C++ added such feature, this above looks like a Python version, Rust has it, Scala had them as one of the first "OOP" languages.

It's nice to see that Haskell pioneered a very useful and now spreading language feature!

Re:Examples of Incorrect Abstractions in Other Languages by sacado2 on Wednesday May 20, 2020 @06:05PM (#23252504)
Ada had them before Haskell, and I'm not even sure it was the first language with them.
Re:Examples of Incorrect Abstractions in Other Languages by naasking on Wednesday May 20, 2020 @08:01AM (#23245817)
> There's no language in which you would be able to write a function for arbitrary data structures using sum(), and get a reasonable outcome.

Computing the number of bytes used by a data type seems perfectly reasonable use of sum in that context. This is also achievable in many languages. All 'sum' needs is a map from a value to a number, which can have many sensible meanings even for arbitrary data types.

Re:Examples of Incorrect Abstractions in Other Languages by dragonwriter on Wednesday May 20, 2020 @11:07AM (#23247740)
And that works in python to, even if the source type is strings:

  sum(map(mappingFunction, iterable))
works fine as long as mappingFunction maps the elements of an iterable to numbers.
Re:Examples of Incorrect Abstractions in Other Languages by throwaway_pdp09 on Wednesday May 20, 2020 @04:41AM (#23244680)
I recently got bitten by trying to do exactly this, concat strings with sum, and spent a while trying to find out if I was being stupid (in this case, no). It damn well should work.

This works

  from functools import reduce
  nums = [1,2,3]
  def add(p, q): return p + q 
  print(reduce(add, nums))
  strs = ["how", "are", "you"]
  print(reduce(add, strs))
so why not that?
Re:Examples of Incorrect Abstractions in Other Languages by rozab on Wednesday May 20, 2020 @05:53AM (#23245039)
Python is a language that seems to make a lot of sense at first but gets a bit weird when you dig into things. The + operator particularly is a bit funny; I recently came across a case where x+=y was not equivalent to x=x+y... Though I can't figure out what it was now.
Re:Examples of Incorrect Abstractions in Other Languages by pansa2 on Wednesday May 20, 2020 @07:47AM (#23245726)
> a case where x+=y was not equivalent to x=x+y

This is true for lists in Python. `a = a + b` creates a new list, but `a += b` works in-place:

    >>> a = [1, 2]
    >>> b = a
    >>> a = a + [3]
    >>> print(a, b)
    [1, 2, 3] [1, 2]

    >>> a = [1, 2]
    >>> b = a
    >>> a += [3]
    >>> print(a, b)
    [1, 2, 3] [1, 2, 3]
There are other issues with the `+=`-style operators as well - IMO it was a mistake to have `a += b` be anything other than a shorthand for `a = a + b`.
Re:Examples of Incorrect Abstractions in Other Languages by tsegratis on Wednesday May 20, 2020 @07:24AM (#23245578)
Agreed, but seems haskell also fails to keep commutativity here tho?

Concatenation is not addition in my opinion

I've often wanted something like bits++bits concatenation to work in the same way for numbers as for strings

Re:Examples of Incorrect Abstractions in Other Languages by throwaway_pdp09 on Wednesday May 20, 2020 @08:08AM (#23245871)
> Concatenation is not addition in my opinion

For python, syntactically it is. In a general sense, an operation is what you define it to be. Just my opinion.

Re:Examples of Incorrect Abstractions in Other Languages by theelous3 on Wednesday May 20, 2020 @07:28AM (#23245598)
You were likely doing something with threads and failed to lock `x`, which I would describe as an issue that should be expected. It doesn't really have to do with `+=` so much as it has to do with being aware of race conditions on variable unprotected by a mutex.
Re:Examples of Incorrect Abstractions in Other Languages by G4E on Wednesday May 20, 2020 @07:40AM (#23245686)
Python's list sum are funny like that.

x+=y is equivalent to x.append(y)

x = x + y creates a new list, then assign it to x (highly inefficient in a loop)

Re:Examples of Incorrect Abstractions in Other Languages by dragonwriter on Wednesday May 20, 2020 @11:21AM (#23247948)
> I recently got bitten by trying to do exactly this, concat strings with sum, and spent a while trying to find out if I was being stupid (

Perhaps not stupid, but ignorant, and not just of the special casing in sum which exist because of a footgun.

sum is basically a readability alternative for functools.reduce for adding numbers, and it's special cased for strings because though it would superficially work for strings otherwise, the performance of repeated string concatenations is pathological in python (as in many garbage-collected languages where it forces many allocations), so a special cases was added which points people to the method to produce exactly the same result without the pathological performance issue.

If you are doing something more complex than numbers with heterogenous data that includes strings in a reduction by the addition operator so that the join you'd use with homogeneous collections of strings isn't what you want (I'm not sure that hypothetical is ever going to happen), use functools.reduce, which for readability you probably should be using in preference to sum() if you aren't doing a mathematical sum anyway.

Re:Examples of Incorrect Abstractions in Other Languages by throwaway_pdp09 on Wednesday May 20, 2020 @11:45AM (#23248249)
Like you, I know the O(n^2) bahaviour that would occur with a naive repeated concatenation, and like you I would know how to deal with it. You'd use "".join(...) for the special case it was strings and therefore so would I. This needn't be a footgun of any sort, and don't assume I (or others) are ignorant.
Re:Examples of Incorrect Abstractions in Other Languages by dragonwriter on Wednesday May 20, 2020 @11:03AM (#23247701)
> If I'm writing a library that needs to handle user-provided data agnostic of type and I want to do a sum operation, now I have to add checks all over the place for whatever special cases python has.

No, you don't, because: (1) if your idea of a sum is just reducing with “+”, you use functools.reduce; and (2) if your idea of sum is a mathematical sum, you use the very slight shortcut of the sum() built-in function, which is (barring things like the runtime type checking) equivalent in result to:

  def sum(iterable, start=0): 
    return functools.reduce(lambda x,y: x+y, iterable, start)
Re:Examples of Incorrect Abstractions in Other Languages by sacado2 on Wednesday May 20, 2020 @06:02PM (#23252470)
What's a sum operation though? Is the sum of a, b and c the same thing as the sum of b, c and a?
Re:Examples of Incorrect Abstractions in Other Languages by Veedrac on Wednesday May 20, 2020 @08:46AM (#23246222)
You needed those checks anyway. Python is just making sure you don't forget.
Re:Examples of Incorrect Abstractions in Other Languages by encypruon on Wednesday May 20, 2020 @05:34AM (#23244934)
There is a rather silly "workaround":

  In [17]: class Start(object): 
      ...:     def __add__(self, other): 
      ...:         return other 
      ...:                                                                                                                                                                                                                                     
  In [18]: sum(["a", "b", "c"], start=Start())                                                                                                                                                                                                 
  Out[18]: 'abc'
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.
Re:Examples of Incorrect Abstractions in Other Languages by alexbanks on Wednesday May 20, 2020 @02:26AM (#23243865)
Re:Examples of Incorrect Abstractions in Other Languages by maest on Wednesday May 20, 2020 @06:03AM (#23245092)
Besides being kinda flippant, I don't see how this aids the discussion in any way.
Re:Examples of Incorrect Abstractions in Other Languages by theelous3 on Wednesday May 20, 2020 @07:39AM (#23245681)
The meme summaries the point very well: "haskell people will say anything that isn't haskell isn't haskell, and is therefore bad".

It's ok for a meme to be relevant sometimes. Don't have to do a bunch of intellectual eye rolling just because a Simpsons character is making the point.

Re:Examples of Incorrect Abstractions in Other Languages by alexbanks on Wednesday May 20, 2020 @11:50AM (#23248304)
I agree with the person I responded to - this isn't an honest view of incorrect abstractions in other languages. This is haskellers complaining that other languages are different. The meme I think accurately conveys that, and why not have a meme every now and then?
Re:Examples of Incorrect Abstractions in Other Languages by jgwil2 on Wednesday May 20, 2020 @12:26AM (#23243294)
What you just described is a leaky abstraction: you need to understand implementation details in order for it to make sense. Your overall point may be valid but the example seems in that sense to be poorly designed.
Re:Examples of Incorrect Abstractions in Other Languages by enriquto on Wednesday May 20, 2020 @04:09AM (#23244483)
The problem here is that using "sum" or "+" for string concatenation is an idiotic choice of words in the base language (because concatenation is not commutative).
Re:Examples of Incorrect Abstractions in Other Languages by iainmerrick on Wednesday May 20, 2020 @07:18AM (#23245546)
Right! Isn’t concatenation “++” rather than “+” in Haskell for exactly that reason?

So if “sum” is a shortcut for “fold with +”, summing a list of strings wouldn’t make sense.

Python still isn’t as regular as it could be, of course, as it does use “+” for concatenating strings.

I think this can all be justified for ergonomic reasons -- using the simple “+” for strong concatenation is convenient, but “sum” is discouraged for strings because it’s slow.

It would be interesting to see a parallel-universe Python that didn’t allow “+” on strings. I wonder if it would have caught on.

Re:Examples of Incorrect Abstractions in Other Languages by enriquto on Wednesday May 20, 2020 @09:36AM (#23246628)
Literally any symbol other than "+" would work better for string concatenation. For example, the product, the comma, a dot, a space (but this might require other changes in the language), or heck, even the minus sign!
Re:Examples of Incorrect Abstractions in Other Languages by crimsonalucard1 on Wednesday May 20, 2020 @07:49AM (#23245746)
It's incorrect because of consistency issues. Sum works with every overloaded + operator. This is not a Haskell thing nor is it a "personal definition" of correct. People expect a definition to be consistent, this is a generally prevalent notion that transcends the boundaries of "personal" as the general population agrees with this notion.

Due to this, under a general definition of "correct" without the context of Haskell such a thing is still classified as generally incorrect. Instead it is more accurate to phrase it as "this is Guido's personal definition of correct." Not that there's anything wrong with that but this is generally unusual and opinionated behavior encoded into python and I wish people will acknowledge that.

Re:Examples of Incorrect Abstractions in Other Languages by antonvs on Wednesday May 20, 2020 @02:05AM (#23243753)
In Haskell, `sum` adds a collection of numbers, i.e. instances of the Num typeclass:

    Prelude> sum ["a", "b"]

    <interactive>:4:1: error:
    • No instance for (Num [Char]) arising from a use of ‘sum’
    • In the expression: sum ["a", "b"]
      In an equation for ‘it’: it = sum ["a", "b"]
You appear to be refuting a straw man.