Conversation
32b2d1a to
060b6fc
Compare
std/algorithm/sorting.d
Outdated
| Merge!(less, Rs) merge(alias less = "a < b", Rs...) | ||
| (Rs rs) | ||
| /** | ||
| Merge multiple sorted ranges $(D rs) with less-than predicate function $(D |
There was a problem hiding this comment.
for single words prefer backticks to the D macro
std/algorithm/sorting.d
Outdated
| /** | ||
| Merge multiple sorted ranges $(D rs) with less-than predicate function $(D | ||
| pred) into one single sorted output range containing the sorted union of the | ||
| elements of inputs. Elements in the output are not unique, that is the length |
There was a problem hiding this comment.
s/that is/consequently/
Better yet, rephrase the sentence: "Duplicates are not eliminated, meaning that the total number of elements in the result of merge is the sum of all elements in the ranges passed to it."
std/algorithm/sorting.d
Outdated
| Details: | ||
|
|
||
| All of its inputs are assumed to be sorted. This can mean that inputs are | ||
| instances of $(XREF range, SortedRange). Use the result of $(XREF algorithm, |
There was a problem hiding this comment.
there is no such restriction in Merge or merge
There was a problem hiding this comment.
Ahh, hang on I'll remove this doc.
std/algorithm/sorting.d
Outdated
| This algorithm is lazy, doing work progressively as elements are pulled off | ||
| the result. | ||
|
|
||
| Average complexity is $(BIGOH n * k) for $(D k) inputs of maximum length $(D n). |
There was a problem hiding this comment.
"Time complexity is proportional to the sum of element counts over all ranges."
| assert(equal(c.retro, [5, 4, 3, 2, 1, 0])); | ||
| ------- | ||
| */ | ||
| Merge!(less, Rs) merge(alias less = "a < b", Rs...)(Rs rs) |
There was a problem hiding this comment.
The constraints should go here, in the user-visible and documented API, not in the Merge struct. The constraint should not use the package-level CommonElementType.
There was a problem hiding this comment.
Done. But we should keep the restriction on Merge because its public and used by setops, right? Later when setUnion is removed we can perhaps turn it into a Voldemort type.
std/algorithm/sorting.d
Outdated
| assert(m.empty); | ||
| } | ||
|
|
||
| package template CommonElementType(Rs...) |
|
You may assert that the ranges are sorted opportunistically; an eager call to isSorted seems a bit much. |
|
So no debug assertions of sortedness of output either, then? Such a checking can be implemented inside |
b877135 to
5db822d
Compare
|
Only thing left now is potential checking for sortedness in |
std/algorithm/sorting.d
Outdated
| A range containing the union of the given ranges. | ||
|
|
||
| See_Also: | ||
| $(XREF algorithm, setops, SetUnion) |
There was a problem hiding this comment.
Please use REF instead of XREF throughout.
std/algorithm/sorting.d
Outdated
| A range containing the union of the given ranges. | ||
|
|
||
| See_Also: | ||
| $(REF algorithm, setops, SetUnion) |
There was a problem hiding this comment.
REF has a different order of arguments than XREF. Symbol name goes first, followed by the module including std. Here: REF(SetUnion, std,algorithm,setops). However, there doesn't seem to be a std.algorithm.setops.SetUnion.
There was a problem hiding this comment.
Done. I presume it's because setUnion has been deprecated by merge.
std/algorithm/sorting.d
Outdated
| A range containing the union of the given ranges. | ||
|
|
||
| See_Also: | ||
| $(REF setUnion, std,algorithm,setops) |
There was a problem hiding this comment.
Alright, syntax is correct now. But the link is dead because setUnion has been undocumented. I suggest to just drop the See_Also section.
std/algorithm/sorting.d
Outdated
|
|
||
| All of its inputs are assumed to be sorted. This can mean that inputs are | ||
| instances of $(REF SortedRange, std,range). Use the result of $(REF sort, | ||
| std,algorithm), or $(REF assumeSorted, std,range) to merge ranges known to be sorted |
There was a problem hiding this comment.
The REF to sort is broken. It's std.algorithm.sorting.sort, so the REF must be $(REF sort, std,algorithm,sorting).
c856406 to
25aa2e8
Compare
|
Ok, REFs look good to me. |
|
Added debug-only efficient checking for sortedness inside I'm satisfied now. |
16553de to
c263e97
Compare
Current coverage is 89.39% (diff: 93.40%)@@ master #4888 diff @@
==========================================
Files 124 124
Lines 76659 76704 +45
Methods 0 0
Messages 0 0
Branches 0 0
==========================================
+ Hits 68527 68570 +43
- Misses 8132 8134 +2
Partials 0 0
|
|
@andralex ping |
|
As I mentioned via email I'm on the road this week. |
|
Ok. Thanks, @andralex Can anyone else approve this? |
| assert(equal(c, [0, 1, 2, 3, 4, 5])); | ||
| assert(equal(c.retro, [5, 4, 3, 2, 1, 0])); | ||
| ------- | ||
| */ |
There was a problem hiding this comment.
Unless I'm missing something, the documentation should have a See_Also section linking to setUnion, and an explanation for how this function is different from it.
There was a problem hiding this comment.
Ok, I'll add a ref. Notice however that setUnion is not visible online anymore. I find that strange. Is this intentional?
There was a problem hiding this comment.
Oh, that's because it's been deprecated in favor of merge. I guess I was missing something after all. Never mind :)
a993e9c to
b701476
Compare
|
On 11/21/2016 10:53 PM, Per Nordlöw wrote:
You're mistaken. The break applies to the foreach. The behavior is a bit To break the switch instead, use a label: sw: switch (foo)
{
foreach (x; alias_seq)
{
case x: /* ... */ break sw;
}
} |
b701476 to
2b2c7aa
Compare
|
@aG0aep6G Changed the two switch breaks to be labeled. |
2b2c7aa to
2aad6cc
Compare
|
And cleaned up the order of the imports and private defs at the top of |
2aad6cc to
8cf4fcc
Compare
Sorry, I'm not following the actual objective of this PR. Just skimming the messages. By the way, I think you've edited in that question later on. It's not in the notification email from GItHub. I wouldn't have noticed it if I hadn't had this page open in the browser. Also, you seem to update the PR by amending. In my experience, that makes it much harder to review the changes. I'd suggest to squash once at the end instead of amending. But Andrei does the actual review here, so that's his call. |
|
Removed |
|
Ok, I'll change to not amending and then squashing at the end. |
std/algorithm/sorting.d
Outdated
| static if (isBidirectional) | ||
| { | ||
| _crt = _crt.max; | ||
| this._lastBackIndex = size_t.max; // uinitialized, lazy initialized in `front` |
There was a problem hiding this comment.
Why is this here and not in the initializer of the field?
There was a problem hiding this comment.
Removed this assignments because it's initialized to size_t in declaration.
std/algorithm/sorting.d
Outdated
| Unqual!ElementType bestElement; | ||
| foreach (i, _; Rs) | ||
| { | ||
| if (source[i].empty) { continue; } |
There was a problem hiding this comment.
This is unusual, for single statements on one line we omit the braces (except when required e.g. for function definitions).
| comp(source[i].front, previousBack), | ||
| "Input " ~ i.stringof ~ " is unsorted"); // @nogc | ||
| } | ||
| break sw; |
There was a problem hiding this comment.
as an aside, the label is not necessary - you may just leave the break here and insert one right after the foreach loop
There was a problem hiding this comment.
I don't understand. Does that revert back to the first state, where this break associates with static foreach instead of the final switch?
There was a problem hiding this comment.
The suggestion is to have two unlabeled breaks, one inside the foreach and another one right after it. But it's really up to you.
std/algorithm/sorting.d
Outdated
| alias opDollar = length; | ||
| } | ||
|
|
||
| public Rs source; |
There was a problem hiding this comment.
we usually put the state at the beginning
8cf4fcc to
610c32c
Compare
47c762b to
5df9c70
Compare
|
Rebased on master. One thing has changed: improved sortedness checking by breaking out CT-logic into |
5df9c70 to
8b859b5
Compare
|
ci/circleci — Your tests failed on CircleCI fails. Don't know why. Should I repush? |
wilzbach
left a comment
There was a problem hiding this comment.
ci/circleci — Your tests failed on CircleCI fails. Don't know why. Should I repush?
Have a look at the output. In the last weeks the CI testing has been improved.
I tried to explain the issues, but in general you can also run the tests locally, e.g. with make -f posix.mak style
std/algorithm/sorting.d
Outdated
| auto c = merge(a.assumeSorted, b.assumeSorted) | ||
| assert(equal(c, [0, 1, 2, 3, 4, 5])); | ||
| assert(equal(c.retro, [5, 4, 3, 2, 1, 0])); | ||
| ------- |
There was a problem hiding this comment.
Any reason why this is a Ddoc unittest block?
If you put it as a normal unittest block and annotate it with the magic /// slashes it will be displayed in the same way, but it has the advantage that we can ensure that the examples does compile. Another advantage is that soon the users will be able to directly run unittests blocks on dlang.org and then of course we will enable this only for tests for which we can ensure they compile & work.
There was a problem hiding this comment.
I didn't add this. It's ok to move it to a unittest if ok with the original author.
There was a problem hiding this comment.
Ok, I removed it and added a test for bidirectional use (via .retro) of merge result in an existing unittest. Use of assumeSorted isn't revelant anymore.
std/algorithm/sorting.d
Outdated
| /// test bi-directional access and common type | ||
| @safe pure nothrow unittest | ||
| { | ||
| import std.algorithm : equal; |
There was a problem hiding this comment.
Output of make -f posix.mak style:
grep -nr 'import std.algorithm : ' $(find . -name '*.d') ; test $? -eq 1
./std/algorithm/sorting.d:1308: import std.algorithm : equal;
make: *** [style] Error 1
-> std.algorithm.comparison
std/algorithm/sorting.d
Outdated
|
|
||
| auto m = merge(a, b, c); | ||
|
|
||
| static assert(is(typeof(m.front) == CommonType!(S, I, D))); |
There was a problem hiding this comment.
output of make -f posix.mak publictests:
executing out/std_algorithm_sorting.d
out/std_algorithm_sorting.d(165): Error: template instance CommonType!(S, I, D) template 'CommonType' is not defined
out/std_algorithm_sorting.d(165): Error: static assert (is(double == _error_)) is false
make: *** [publictests] Error 1
As mentioned above we want to ensure that public tests do compile without missing imports and hence we started to automatically check for it. So a public unittest block can't use the global imports.
Solution 1: use the ddoced example as public unittest and make this one private
Solution 2: add the missing import -> import std.traits : CommonType
There was a problem hiding this comment.
Added the import for CommonType.
| @property bool empty() | ||
| { | ||
| return _crt == _crt.max; | ||
| size_t bestIndex = size_t.max; // indicate undefined |
There was a problem hiding this comment.
With ptrdiff_t you could use -1 - this seems to be used at a couple of similar bits at Phobos, e.g.
https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L881
https://github.com/dlang/phobos/blob/master/std/string.d#L383
Explanation:
http://en.cppreference.com/w/cpp/types/ptrdiff_t
There was a problem hiding this comment.
Why is ptrdiff_t preferred over size_t here? bestIndex is an absolute index here not a difference.
0b4e8b9 to
3125beb
Compare
wilzbach
left a comment
There was a problem hiding this comment.
import std.range: retro is still missing :/
| int[] b = [2, 3, 4]; | ||
|
|
||
| assert(a.merge(b).equal([1, 2, 3, 3, 4, 5])); | ||
| assert(a.merge(b).retro.equal([5, 4, 3, 3, 2, 1])); |
There was a problem hiding this comment.
make -f publictests or CircleCi
out/std_algorithm_sorting.d(202): Error: no property 'retro' for type 'Merge!("a < b", int[], int[])'
There was a problem hiding this comment.
Don't you mean: make -f posix.mak publictests?
There was a problem hiding this comment.
Don't you mean: make -f posix.mak publictests?
Yes - sorry for the typo.
std/algorithm/sorting.d
Outdated
| static assert(is(typeof(m.front) == CommonType!(S, I, D))); | ||
|
|
||
| assert(equal(m, [1, 2, 3, 10, 20, 30, 40, 50, 60])); | ||
| assert(equal(m.retro, [60, 50, 40, 30, 20, 10, 3, 2, 1])); |
There was a problem hiding this comment.
make -f publictests or CircleCi
out/std_algorithm_sorting.d(169): Error: no property 'retro' for type 'Merge!("a < b", short[], int[], double[])'
|
|
||
| /// | ||
| @safe pure nothrow unittest | ||
| { |
There was a problem hiding this comment.
It might be a personal preference, but I show the simpler unittest example as first example to the user.
There was a problem hiding this comment.
Done. Moved the longer unittest last.
3125beb to
28153fb
Compare
|
Ready to pull? |
| } | ||
| final switch (_lastBackIndex) | ||
| { | ||
| foreach (i, _; Rs) |
There was a problem hiding this comment.
eh, line shown mistakenly as not covered
| private alias ElementType = CommonType!(staticMap!(.ElementType, Rs)); | ||
| private enum isBidirectional = allSatisfy!(isBidirectionalRange, staticMap!(Unqual, Rs)); | ||
|
|
||
| debug private enum canCheckSortedness = isCopyable!ElementType && !hasAliasing!ElementType; |
There was a problem hiding this comment.
Guess this would be a version:
debug static if (isCopyable!ElementType && !hasAliasing!ElementType)
version = can_check_sortedness;Unsure on which is the best way.
|
Good engineering, thanks. |
This is revival of my previous #3315 applied on top of existing implementation of
mergethat sneaked in without me noticing it ;)Improvements:
popFrontandpopBack. Done by comparing current and next element if element type allows it.Other notes:
isSortedRangein my previous implementation has been removed because we currently cannot compare all the different formats for the comparison alias (pred) fed toSortedRange.Update:
I just noticed that
Mergeis used in setops. I guess this removes the opportunity for making this a Voldermort type, right?