digitalmars.D - So... add maxCount and maxPos?
- Andrei Alexandrescu (4/4) Jan 20 2016 This is one of those cases in which we were pedantically right to not
- H. S. Teoh via Digitalmars-d (9/13) Jan 20 2016 [...]
- Andrei Alexandrescu (3/13) Jan 20 2016 extremumPos has been on my wish list for a while now, but (a) we're
- H. S. Teoh via Digitalmars-d (8/23) Jan 20 2016 If renaming is out of the question, then I suppose maxPos/maxCount would
- Timon Gehr (2/11) Jan 20 2016 The predicate always describes an order relative to which to find a mini...
- Era Scarecrow (10/27) Jan 21 2016 maxCount sounds too much like it's suppose to be a function in
- Andrei Alexandrescu (2/4) Jan 21 2016 minCount is already a given. -- Andrei
- Iakh (3/8) Jan 21 2016 countMost!less and posMost!less
- Era Scarecrow (9/13) Jan 23 2016 I have a slight problem where I'm not already familiar with most
- Ivan Kazmenko (22/25) Jan 20 2016 As it seems related, let me share my personal experience with
- Andrei Alexandrescu (11/27) Jan 20 2016 Sadly, no. I'm very willing to add an overload of min and max for one
- Ivan Kazmenko (52/77) Jan 20 2016 Hmm. I was at first frustrated by not having min(Range). But I
- Andrei Alexandrescu (2/3) Jan 20 2016 OK, convinced. There's of course the option of (min|max)Element. -- Andr...
- default0 (14/19) Jan 21 2016 As a newcomer to the language, and as a reader of
- Ivan Kazmenko (19/39) Jan 21 2016 Still, looks like Java, C# and Python have min work this way:
- tn (4/19) Jan 21 2016 But (min|max)(Index|Key) offer different type of flexibility as
- Timon Gehr (6/10) Jan 20 2016 One reason why dual notions usually both receive names is that naming
This is one of those cases in which we were pedantically right to not add them, but their equivalents look like crap. https://github.com/D-Programming-Language/phobos/pull/3942 Andrei
Jan 20 2016
On Wed, Jan 20, 2016 at 12:16:00PM -0500, Andrei Alexandrescu via Digitalmars-d wrote:This is one of those cases in which we were pedantically right to not add them, but their equivalents look like crap. https://github.com/D-Programming-Language/phobos/pull/3942[...] I don't like this. I'd much rather we rename those functions to be something more generic. After all, minPos is a horrible name when the predicate has nothing to do with minimum values. What about extremumPos? (Though that's rather ugly to type.) T -- People demand freedom of speech to make up for the freedom of thought which they avoid. -- Soren Aabye Kierkegaard (1813-1855)
Jan 20 2016
On 01/20/2016 12:29 PM, H. S. Teoh via Digitalmars-d wrote:On Wed, Jan 20, 2016 at 12:16:00PM -0500, Andrei Alexandrescu via Digitalmars-d wrote:extremumPos has been on my wish list for a while now, but (a) we're stuck with minPos anyway, (b) extremumPos sounds elitist. -- AndreiThis is one of those cases in which we were pedantically right to not add them, but their equivalents look like crap. https://github.com/D-Programming-Language/phobos/pull/3942[...] I don't like this. I'd much rather we rename those functions to be something more generic. After all, minPos is a horrible name when the predicate has nothing to do with minimum values. What about extremumPos? (Though that's rather ugly to type.)
Jan 20 2016
On Wed, Jan 20, 2016 at 02:30:10PM -0500, Andrei Alexandrescu via Digitalmars-d wrote:On 01/20/2016 12:29 PM, H. S. Teoh via Digitalmars-d wrote:If renaming is out of the question, then I suppose maxPos/maxCount would be the next less evil. :-P If we ever get to D3, this would be one of the things that should be changed... but until then, I guess we can live with maxPos/maxCount. T -- Error: Keyboard not attached. Press F1 to continue. -- Yoon Ha Lee, CONLANGOn Wed, Jan 20, 2016 at 12:16:00PM -0500, Andrei Alexandrescu via Digitalmars-d wrote:extremumPos has been on my wish list for a while now, but (a) we're stuck with minPos anyway, (b) extremumPos sounds elitist. -- AndreiThis is one of those cases in which we were pedantically right to not add them, but their equivalents look like crap. https://github.com/D-Programming-Language/phobos/pull/3942[...] I don't like this. I'd much rather we rename those functions to be something more generic. After all, minPos is a horrible name when the predicate has nothing to do with minimum values. What about extremumPos? (Though that's rather ugly to type.)
Jan 20 2016
On 01/20/2016 06:29 PM, H. S. Teoh via Digitalmars-d wrote:On Wed, Jan 20, 2016 at 12:16:00PM -0500, Andrei Alexandrescu via Digitalmars-d wrote:The predicate always describes an order relative to which to find a minimum.This is one of those cases in which we were pedantically right to not add them, but their equivalents look like crap. https://github.com/D-Programming-Language/phobos/pull/3942[...] I don't like this. I'd much rather we rename those functions to be something more generic. After all, minPos is a horrible name when the predicate has nothing to do with minimum values.
Jan 20 2016
On Wednesday, 20 January 2016 at 17:29:28 UTC, H. S. Teoh wrote:On Wed, Jan 20, 2016 at 12:16:00PM -0500, Andrei Alexandrescu via Digitalmars-d wrote:maxCount sounds too much like it's suppose to be a function in SQL querying, and minCount... ugg... now I wonder what in the world we're talking about. From algorithm.d:This is one of those cases in which we were pedantically right to not add them, but their equivalents look like crap.I don't like this. I'd much rather we rename those functions to be something more generic. After all, minPos is a horrible name when the predicate has nothing to do with minimum values. What about extremumPos? (Though that's rather ugly to type.)int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ]; // Minimum is 1 and occurs 3 times assert(a.minCount == tuple(1, 3)); // Maximum is 4 and occurs 2 times assert(a.maxCount == tuple(4, 2)); // Minimum is 1 and first occurs in position 3 assert(a.minPos == [ 1, 2, 4, 1, 1, 2 ]); // Maximum is 4 and first occurs in position 2 assert(a.maxPos == [ 4, 1, 2, 4, 1, 1, 2 ]);These unittests make it completely clear what it wants to do. I'd almost say lowestCount and highestCount would almost be better, but i am not sure. or just unitCount? Or countOf and posOf? which make a lot more sense when instantiated: So a.countOf!("a < b")? I'm seriously behind on all of this.
Jan 21 2016
On 01/21/2016 08:42 AM, Era Scarecrow wrote:I'd almost say lowestCount and highestCount would almost be better, but i am not sure.minCount is already a given. -- Andrei
Jan 21 2016
On Thursday, 21 January 2016 at 14:04:58 UTC, Andrei Alexandrescu wrote:On 01/21/2016 08:42 AM, Era Scarecrow wrote:countMost!less and posMost!lessI'd almost say lowestCount and highestCount would almost be better, but i am not sure.minCount is already a given. -- Andrei
Jan 21 2016
On Thursday, 21 January 2016 at 14:04:58 UTC, Andrei Alexandrescu wrote:On 01/21/2016 08:42 AM, Era Scarecrow wrote:I have a slight problem where I'm not already familiar with most of the standard library functions (D, libc, etc) that are usually available. This usually means I have a naive approach and/or naming convention to what's already been in place 15+ years. Of course when I do take the time to go through the libraries and documentation I'll say 'oohhh that's cool!'; But because I'm not actively using it I'll promptly forget it :(I'd almost say lowestCount and highestCount would almost be better, but I am not sure.minCount is already a given. -- Andrei
Jan 23 2016
On Wednesday, 20 January 2016 at 17:16:00 UTC, Andrei Alexandrescu wrote:This is one of those cases in which we were pedantically right to not add them, but their equivalents look like crap. https://github.com/D-Programming-Language/phobos/pull/3942As it seems related, let me share my personal experience with minPos. Most of the time, I want one of the two things related to an extremum. 1. The minimum or maximum element itself. I write it as a.minPos.front. That's almost fine, but maybe there is a more expressive way? 2. The index of minimum or maximum element, mostly using plain array as a range. I write "a.length - a.minPos.length", and it looks completely unintuitive. Additionally, when compiling to 64 bits, I usually still want an int to use with other ints around (longs are overkill most of the time), and the cast adds more clobber. Again, is there a better way to express that? 3. Other uses: I've yet to see the need. In a random collection of my D code, the number of occurrences of cases 1:2:3 is 6:4:0. I've got used to "minPos !(q{a > b})" instead of "maxPos", but a maxPos alias would of course make things a bit more clear. Don't know how much of a justification that is. Ivan Kazmenko.
Jan 20 2016
On 01/20/2016 04:22 PM, Ivan Kazmenko wrote:On Wednesday, 20 January 2016 at 17:16:00 UTC, Andrei Alexandrescu wrote:Sadly, no. I'm very willing to add an overload of min and max for one argument (which fortunately does not compile currently) to compute these over a range. In fact literally today I wrote r.min and was surprised it didn't work. Would you want to embark on that? Code, docs, unittests, the works.This is one of those cases in which we were pedantically right to not add them, but their equivalents look like crap. https://github.com/D-Programming-Language/phobos/pull/3942As it seems related, let me share my personal experience with minPos. Most of the time, I want one of the two things related to an extremum. 1. The minimum or maximum element itself. I write it as a.minPos.front. That's almost fine, but maybe there is a more expressive way?2. The index of minimum or maximum element, mostly using plain array as a range. I write "a.length - a.minPos.length", and it looks completely unintuitive. Additionally, when compiling to 64 bits, I usually still want an int to use with other ints around (longs are overkill most of the time), and the cast adds more clobber. Again, is there a better way to express that?No better way currently. We could add (min|max)Index but I like (min|max)Pos quite a bit. They offer more flexibility for non-random access ranges. For random access ranges you should soon be able to write a.before(a.minPos).length, for a different kind of unintuitiveness :o). Andrei
Jan 20 2016
On Thursday, 21 January 2016 at 01:11:19 UTC, Andrei Alexandrescu wrote:On 01/20/2016 04:22 PM, Ivan Kazmenko wrote:Hmm. I was at first frustrated by not having min(Range). But I looked for a reason it does not yet exist, and I found one. Say we define min of one argument, which is a range, to be the minimum value of that range. Now, what if we unpack tuples as arguments for min, and some tuple happens to have one element, which is a range? Currently, this immediately triggers a compile error. On the other hand, if we add the one-argument range version, it will silently produce a value of another type. As all of this may happen only at compile time, and the type system is rather strict, hopefully this will hit a compile error down the road, but even then, the actual cause will be harder to find. An example: ----- import std.algorithm, std.range, std.stdio, std.typecons; alias minBinary = (x, y) => x < y ? x : y; auto min (Args...) (Args args) if (args.length > 1) { return args.only.reduce!minBinary; } auto min (T) (T [] arr) { return arr.reduce!minBinary; } void main () { writeln (min (3, 1, 2)); // 1 writeln (min ([3, 1, 2])); // 1 writeln (min (tuple ([5, 6], [1, 2], [3, 4]).expand)); // [1, 2] writeln (min (tuple ([3, 1, 2]).expand)); // 1, huh? } ----- So, min(Range) + tuple expansion = problem. An alternative would be to define min(one argument) to just be that argument. That would be consistent with what we have now, but violates the principle of least astonishment for newcomers: why would min ([3, 1, 2]) return [3, 1, 2] and not 1? Currently, it just does not compile. So, I convinced myself that the current situation is the lesser evil. Currently, the second and fourth writeln in the example just don't compile if we comment out our min functions.1. The minimum or maximum element itself. I write it as a.minPos.front. That's almost fine, but maybe there is a more expressive way?Sadly, no. I'm very willing to add an overload of min and max for one argument (which fortunately does not compile currently) to compute these over a range. In fact literally today I wrote r.min and was surprised it didn't work. Would you want to embark on that? Code, docs, unittests, the works.Well, this at least reads a bit like English: take the part of "a" before minimum position in "a" and calculate its length. The downside is two uses of "a" which are certain to put more burden on the optimizer. The current "whole length minus length after minimum" is a negative wording, which adds to perceived complexity every time it is used. Ivan Kazmenko.2. The index of minimum or maximum element, mostly using plain array as a range. I write "a.length - a.minPos.length", and it looks completely unintuitive. Additionally, when compiling to 64 bits, I usually still want an int to use with other ints around (longs are overkill most of the time), and the cast adds more clobber. Again, is there a better way to express that?No better way currently. We could add (min|max)Index but I like (min|max)Pos quite a bit. They offer more flexibility for non-random access ranges. For random access ranges you should soon be able to write a.before(a.minPos).length, for a different kind of unintuitiveness :o).
Jan 20 2016
On 01/20/2016 09:36 PM, Ivan Kazmenko wrote:So, min(Range) + tuple expansion = problem.OK, convinced. There's of course the option of (min|max)Element. -- Andrei
Jan 20 2016
On Thursday, 21 January 2016 at 02:36:05 UTC, Ivan Kazmenko wrote:An alternative would be to define min(one argument) to just be that argument. That would be consistent with what we have now, but violates the principle of least astonishment for newcomers: why would min ([3, 1, 2]) return [3, 1, 2] and not 1? Currently, it just does not compile.As a newcomer to the language, and as a reader of https://dlang.org/phobos/std_algorithm_comparison.html#min which states "Iterates the passed arguments and returns the minimum value." my intuitive understanding would be that yes of course min(x) returns x. However the above could of course also be reworded as "Iterates the passed list of arguments and returns the minimum value." to be even more clear about it NOT iterating individual arguments but the argument list as a whole :-) If I were to be a newcomer to programming in general this might be confusing, though. However, it's certainly consistent and easy to wrap your head around and also what I would have expected it to do the first time I came across the function.
Jan 21 2016
On Thursday, 21 January 2016 at 12:17:26 UTC, default0 wrote:On Thursday, 21 January 2016 at 02:36:05 UTC, Ivan Kazmenko wrote:given a single argument which is a collection, it returns the minimum in that collection, not the collection itself. A Python example: min ([1]) // 1 min ([2, 1]) // 1 min ((([1, 2], [2, 3]))) // [1, 2] min ((([1, 2]))) // 1 min ((([1, 2],),)) // ([1, 2],) In Python, the what happens is also tricky: def g(): return (1, 2) // tuple of two values g() // (1, 2) min (g()) // 1 from tuple min (*g()) // 1 from expanded tuple def f(): return (1,) // tuple of a single value f() // (1,) min (f()) // 1 min (*f()) // error, cannot expandAn alternative would be to define min(one argument) to just be that argument. That would be consistent with what we have now, but violates the principle of least astonishment for newcomers: why would min ([3, 1, 2]) return [3, 1, 2] and not 1? Currently, it just does not compile.As a newcomer to the language, and as a reader of https://dlang.org/phobos/std_algorithm_comparison.html#min which states "Iterates the passed arguments and returns the minimum value." my intuitive understanding would be that yes of course min(x) returns x. However the above could of course also be reworded as "Iterates the passed list of arguments and returns the minimum value." to be even more clear about it NOT iterating individual arguments but the argument list as a whole :-) If I were to be a newcomer to programming in general this might be confusing, though. However, it's certainly consistent and easy to wrap your head around and also what I would have expected it to do the first time I came across the function.
Jan 21 2016
On Thursday, 21 January 2016 at 01:11:19 UTC, Andrei Alexandrescu wrote:On 01/20/2016 04:22 PM, Ivan Kazmenko wrote:But (min|max)(Index|Key) offer different type of flexibility as those make sense for associative containers.2. The index of minimum or maximum element, mostly using plain array as a range. I write "a.length - a.minPos.length", and it looks completely unintuitive. Additionally, when compiling to 64 bits, I usually still want an int to use with other ints around (longs are overkill most of the time), and the cast adds more clobber. Again, is there a better way to express that?No better way currently. We could add (min|max)Index but I like (min|max)Pos quite a bit. They offer more flexibility for non-random access ranges.
Jan 21 2016
On 01/20/2016 06:16 PM, Andrei Alexandrescu wrote:This is one of those cases in which we were pedantically right to not add them, but their equivalents look like crap. https://github.com/D-Programming-Language/phobos/pull/3942 AndreiOne reason why dual notions usually both receive names is that naming one of them but not the other is arbitrary and confusing. (Reversing all arrows in the respective category is often just not a very natural operation, even if it has a computational interpretation.) Languages don't just leave out one of && or || either.
Jan 20 2016