sort API design

mipri mipri at
Fri Nov 22 02:25:42 UTC 2019

On Thursday, 21 November 2019 at 23:28:48 UTC, Jonathan M Davis 
> So, I'm sorry that you gotten bitten by sort not working the
> way you expected, but I don't see how that could have been
> prevented without implementing the range in the way that you
> expected, which would then screw over anyone who assumed that
> the range would be sorted in-place.

I don't disagree, but the problem also wasn't presented as a 
of Phobos, but as "I did wrote this code. I learned it was wrong.
How might my error have been averted?"

 From some other languages,

| Language | Sort        | Mutates? | Returns? | Both? |
| Perl     | sort        | No       | Yes      | No    |
| Python   | list.sort   | Yes      | No       | No    |
| Python   | list.sorted | No       | Yes      | No    |
| C        | qsort       | Yes      | No       | No    |
| C++      | std::sort   | Yes      | No       | No    |
| Rust     | vec::sort   | Yes      | No       | No    |

The norm is to do one or the other, and not both.

Why does D do both? Because it has an efficiency focus (avoid
unnecessary copying) and also an expressiveness focus (go ahead 
do things with long pipelines of transformations), and this
combination is uncommon.

Actually I'm surprised Rust doesn't do both... and come to think 
it, I *was* surprised by that, when I rewrote a benchmark in it: I
tried putting the .sort_by() in the middle of a pipeline of
function calls and was confused by the error. So I had the exact
opposite "I did a thing. I learned it was wrong." problem with
sorting in Rust.

There's another reason D does both: 
is how you build pipelines in D, and each of these change()
functions needs to return the input to the next change(). But 
this isn't a deliberate language feature, it's not taking 
of "pipeline syntax", it's just a consequence of how methods work
in OOP languages.

So it's more like a pattern :) One of those awful things that
highlights a failure of language design, where programmers, 
of directly expressing their intentions with code, must 
work around a void in the language. Or so I hear.

Suppose, instead of expecting D programmers to make use of the
"collection pipelien" pattern, D just had a collection pipeline
feature? Like:

   thing |> change1() |> change2() |> change3()

If it's a language feature, D can, since it knows the types of all
these functions, apply a rule like

   if a function is void, reuse the last input for the next 
   otherwise, behave like . chaining

With this, Phobos could have a void sort that could still appear 
the middle of a long pipeline of transformations, and confusions
like the one in this thread about Phobos, and *also* the one I had
about Rust's sort, would both not be possible.

Instead you'd have the new potential confusion of thinking that
sort doesn't mutate because you saw it in a pipeline :)

To be clear, I don't recommend changing anything. I just think 
not true that D has nothing to do with this.

More information about the Digitalmars-d mailing list