Skip to content

Conversation

@wilzbach
Copy link
Contributor

resubmisson of #4019 - as extremum turned out not to be very useful, I changed it to accept directly the mapping function. This is now more efficient as the mapping function is called only once :)

@andralex has already approved the name:

Overall I think this is rather foreign compared to prevalent Phobos style. I think extremum,minElement, and maxElement with the appropriate predicates are the way to go.

Pinging @JackStouffer @burner @ntrel @klickverbot @JackStouffer


static if (isRandomAccessRange!Range && hasLength!Range)
{
size_t lenArray = r.length;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

immutable

import std.range: enumerate, iota;
assert([2, 1, 4, 3].maxElement == 4);
// allows to get the index too
assert([2, 1, 4, 3].enumerate.maxElement!"a.value" == tuple(2, 4));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs another example of a custom accessor, something like the assert on line 1279

@JackStouffer
Copy link
Contributor

This also needs tests using the dummy ranges, as you have no tests currently with input ranges.

$(D maxCount([2, 4, 1, 4, 1])) returns $(D tuple(4, 2)).)
$(T2 minElement,
Selects the minimal element of a range.
$(D minElement([3, 4, 1, 2])) returns $(D 1).)
Copy link
Contributor

@JackStouffer JackStouffer Apr 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use the new `` style for D code where ever possible. Same throughout.

@JackStouffer
Copy link
Contributor

Also, I forgot to mention that this should also have unit tests with @nogc @safe nothrow pure.

@wilzbach
Copy link
Contributor Author

wilzbach commented Apr 21, 2016

This also needs tests using the dummy ranges, as you have no tests currently with input ranges.
Also, I forgot to mention that this should also have unit tests with @nogc @safe nothrow pure.

Thanks a lot for your review @JackStouffer!
All comments were addressed :)

alias selectorFun = binaryFun!selector;

// init extremum
Unqual!(ElementType!Range) extremeElement = r.front;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick - how about:

alias Element = ElementType!Range;
alias MapType = Unqual!(typeof(mapFun(Element.init)));

Unqual!Element extremeElement = r.front;
MapType extremeElementMapped = mapFun(extremeElement);

(Evaluate r[0] once and make the code a bit more DRY).

@ntrel
Copy link
Contributor

ntrel commented Apr 21, 2016

LGTM besides minor comments.

@wilzbach
Copy link
Contributor Author

LGTM besides minor comments.

Thanks a lot for reviewing this @ntrel - I just addressed your comments.
The only open question so far is whether the specialization for a RandomAccessRange is useful in terms of speed.

@nordlow
Copy link
Contributor

nordlow commented Apr 22, 2016

Is having an assert do the emptyness-checking robust enough? Is this the Phobos-way? Alternatively an enforce or explicit throw could be used instead. Or should we rely on the .front-call in these cases? If we rely on .front throwing why do we need the assert-checking for emptyness?

Further, I would like an optional second parameter, seed, (like is used in std.algorithm.iteration.reduce) that elides this throw-logic for flexibility, "potentially" making things nothrow. That is, in the case when range parameter is empty, function returns seed.

Also, it could be motivated to add links in the docs to

I've seen STL-references to algorithms elsewhere in the Phobos docs.

BTW: Thanks for adding these!

@DmitryOlshansky
Copy link
Member

Is having an assert do the emptyness-checking robust enough? Is this the Phobos-way?

AFAIK asserting with ranges is the style.

@9il
Copy link
Member

9il commented Apr 22, 2016

AFAIK asserting with ranges is the style.

We need to fix std.numeric thought

@nordlow
Copy link
Contributor

nordlow commented Apr 23, 2016

@9il What do you mean by: fixing std.numeric?

@9il
Copy link
Member

9il commented Apr 23, 2016

@9il What do you mean by: fixing std.numeric?

It uses enforce instead of assert. It should be changes to asserts

@9il
Copy link
Member

9il commented Apr 28, 2016

Wait a minute please

@9il
Copy link
Member

9il commented Apr 28, 2016

assert([2, 1, 4, 3].enumerate.reduce!((a, b) => a.value > b.value ? a : b) == tuple(2, 4));

What wrong with this code?

@9il
Copy link
Member

9il commented Apr 28, 2016

If we are so lazy to write lambdas then just allow min/max to accept map function instead ;-)

@wilzbach
Copy link
Contributor Author

wilzbach commented Apr 28, 2016

What wrong with this code?

It evaluates the map function twice ;-)

If we are so lazy to write lambdas then just allow min/max to accept map function instead ;-)

Yes I would love to see min working for ranges! See my comment at #4019

As you mentioned a lot of languages (Java, C#, Python, more at Rosetta) allow min to be used with one argument and as still being a newcomer to D I feel that many people like me will just expect [1,2,3].min to work.

@9il
Copy link
Member

9il commented Apr 28, 2016

Another option is add combined mapReduce to the iteration module.

@9il
Copy link
Member

9il commented Apr 28, 2016

It evaluates the map function twice ;-)

So we need combined mapReduce

@9il
Copy link
Member

9il commented Apr 28, 2016

But please do not rush to write it right now. We need to think how this can be generalized for multidimensional Slice

@9il 9il added the ndslice label Apr 28, 2016
@wilzbach
Copy link
Contributor Author

btw just a quick update - @9il and I tested for a couple of array types with random access & -release -O3 -boundscheck=off.
-> the variant with RandomAccess is faster (source) (even for ndslice).

@DmitryOlshansky
Copy link
Member

@9il is this good to go?

@wilzbach
Copy link
Contributor Author

@DmitryOlshansky @9il what is your opinion on renaming this to min ? The other min expects two or more parameters and @GassaFM's comment about tuple expansion with a single array in the tuple is seldom and then still understandable.

@9il
Copy link
Member

9il commented Apr 28, 2016

OK, we can move forward. Looks like ndslice will have its own functional

@9il
Copy link
Member

9il commented Apr 28, 2016

@wilzbach min may cause bad behavior with templated code. I prefer current name

@DmitryOlshansky
Copy link
Member

Same here - minElement is established name, and single ard min is problematic in generic code

@DmitryOlshansky
Copy link
Member

Auto-merge toggled on

@9il
Copy link
Member

9il commented Apr 28, 2016

Hmm... how can I use this new functions with http://dlang.org/phobos/std_math.html#.cmp ?

@wilzbach wilzbach deleted the min_max_element branch April 28, 2016 15:02
@wilzbach
Copy link
Contributor Author

how can I use this new functions with http://dlang.org/phobos/std_math.html#.cmp ?

For reference: see #4257 where I propose to make extremum public ;-)

@nordlow
Copy link
Contributor

nordlow commented Apr 28, 2016

Thanks!

@andralex
Copy link
Member

Why are minElement/maxElement not in the documentation at https://dlang.org/phobos/std_algorithm_searching.html?

@wilzbach
Copy link
Contributor Author

Why are minElement/maxElement not in the documentation at https://dlang.org/phobos/std_algorithm_searching.html?

They are part of the 2.072 release (it's quite big due to the long accumulation period - April to September). Hopefully it can be released soon, but with all the regressions popping up it doesn't look good :/

@andralex
Copy link
Member

Thanks for the info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants