-
-
Notifications
You must be signed in to change notification settings - Fork 701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
introduce "fold" to std.algorithm #2033
Conversation
else static if (Args.length == 1) | ||
{ | ||
//Only 1 seed provided. Repeat it as necessary. | ||
RepeatType!(Unqual!(Args[0]), funs.length) result = seeds[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to check here, whether the single seed works with all functions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It always makes sense to add sanity checks. As a matter of fact, you could do it lower in the code, which would end up checking that each seed is valid for their corresponding function.
Some critique/comments in Bugzilla. |
Interest in backporting all of this good work to |
@andralex: the whole point of this issue is to have the iterable as first argument and seed as second, for usage in UFCS chains. How do you plan to do that without changing the name of the function Andrei? |
It is possible to support both argument orders in the same function for the vast majority of argument types, but not all (some would be ambiguous). However, it makes the code even more complex and the documentation even worse. |
As @JakobOvrum said there's been work on that. |
@bearophile had this to say about the design in the bug report. Here are his comments, and my replies: https://d.puremagic.com/issues/show_bug.cgi?id=8755 (In reply to comment #14)
The current most spread phobos style is to accept arguments via vararg, and to I'm not sure it is possible to accept either a Tuple (that "auto expands"
You think? It made sense to me. I'll have to ask for more input on this. That r = a.fold!("a + b", "a + b * b")(0.0, 0.0); //OK! The second one is more verbose, but I see its justified if your seed is already So I think you sold me on it.
It's a deviation, but I think it's justified. It makes the code nothrow, and The only argument I'd accept in its favor is stability with reduce, but if we
OK. I can work them back in. |
I agree that porting things back into reduce is a good idea, and it is planned too. But that wasn't the point of the pull:
Yes, it was I. #861 Long story short, it creates a silent compile-time ambiguity that can only be observable at runtime. And that is absolutely in-acceptable. [4, 5, 6].reduce!"a ~ b"([1, 2, 3]); What would this do? Would it reduce the range [4, 5, 6] into the seed [1, 2, 3], or would it reduce the range [1, 2, 3] into the seed [4, 5, 6]? The problem is that the ambiguity is un-resolveable, and there is no-way to be explicit about which you want: You just have to trust For what it's worth, the above code exists in phobos in the form of strings, so, it's not theoretical. The cleanest, simplest, most non-ambiguous and most non-breaking way to fix the "reduce argument order" issue, is to re-introduce it with a different name. Everything else is "sugar"/"upkeep". Most of it can and will be backported to reduce anyways. So, @andralex : It boils down to only 1 question: There's no moving forward if we don't statute on this point. |
Surely
But I do agree with this. Regardless of whether |
Exactly my point, but...
If we want to deprecate it, there has to be something to migrate to. Which is fold. That said, I think I could make it work so reduce just becomes roughly |
Not if |
I get the idea, but what if I have: [4, 5, 6].reduce!"a ~ b"([1, 2, 3]); Which one is my seed? What is the deprecation message that will appear, and how will I fix it? How can I know which version I'm calling, and how can I tell I want to call the other one? Won't work... |
That's a good point, there would be no way to do this until the completion of the deprecation cycle (at which point the argument order can be switched to fix it). I guess my vote is with |
I also vote for introducing |
No, it can be changed in non-breaking ways. |
Thank you for the feedback. There is 1 last thing I want to discuss: I want to make the "no-seed" version of fold assert if the range is empty. Currently, reduce on enforces this. I think it is correct to assert, and make the code nothrow to boot, but it also mean a deviation from reduce. How do you guys feel about this change? Once this is answered, I can go back to hacking at this. |
What would the function return in release mode? |
I'm unsure. Whatever value is produced from calling the |
BRB! |
@monarchdodra Discussion thread on the NG seems in favour of this now (this PR linked in discussion): |
Try 2.
This time, I think the pull is complete, so fire away and destroy anything you like. Should I apply for "formal review"? I'll post about this on the boards after the initial salvo here ;)
fold
is basically still the same thing as reduce, but "fixes" some interface issues that were not fixable without breakage. Namelly, palcing the range before the seed, for UFCS friendliness. Not a huge problem, but a common enough occurrence to cause frustration, and justify fixing.Furthermore, it also improves usability by making the seeds passed by parameter pack, instead of forcing the use of a
tuple
.Finally, it allows using only 1 seed, in which case, the same seed is replicated and is used for all the functions.
Oh yeah, also, I made it so that when no seed is given, it is an
Error
to use an empty range. This is the only case of deviation, but I think having nothrow justifies it."iterables" are not supported anymore.
These changes should make for an overall nicer D experience, and justify the update via a new name. Old code should not be impacted.
Implementation wise, I think
fold
is very neat, and contains lots of improvements overreduce
: Shorter code, better initialization scheme, a better inference mechanism for guessing the seed type...But it doesn't actually contain anything I couldn't port back to reduce afterwards. Most of it anyways I think.