Skip to content
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

Issue 13594: nextPermutation should work with static arrays too. #2650

Closed
wants to merge 3 commits into from

Conversation

quickfur
Copy link
Member

bool nextPermutation(alias less="a<b", StaticArray)(ref StaticArray arr)
if (is(StaticArray == T[n], T, size_t n))
{
auto slice = arr[];
Copy link
Member Author

Choose a reason for hiding this comment

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

Workaround for arr[] not being an lvalue, which is the real cause of the bug.

assert(a == [3, 2, 1]);
assert(!a.nextPermutation());
assert(a == [1, 2, 3]);
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggest templating the test function and doing all the same tests as the original unit tests. They are already all there, no reason not to reuse them :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea. Not sure how to do it in a way that's still simple enough for beginners, though, since the original test is a ddoc'd unittest.

Copy link
Member

Choose a reason for hiding this comment

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

What about reusing the unit test at line 13311?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea, done.

@schveiguy
Copy link
Member

Pretty simple, looks good to me.

@schveiguy
Copy link
Member

Again, LGTM. Thanks.

assert(nextPermutation(a1));
assert(equal(a1, [1, 2, 4, 3]));
assert(nextPermutation(arr));
assert(arr == [1, 3, 4, 2]);
Copy link
Member

Choose a reason for hiding this comment

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

Why have you replaced equal? The test would no longer work with any Range.

Copy link
Member

Choose a reason for hiding this comment

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

It's a nested function inside this unit test. I don't think there's any danger of this issue arising, as the only two arguments to this function are a dynamic array and a static array.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, this is code inside a unittest, so this shouldn't be an issue.

The only reason I changed it was because equal apparently doesn't know how to compare a dynamic array with a static one. :-(

@DmitryOlshansky
Copy link
Member

I'm inclined to say NO.

If anything this trend would mean that we have to special case every algorithm for static arrays. Just use slice.

@quickfur
Copy link
Member Author

The problem is that slice doesn't work because nextPermutation expects a ref argument, and a slice of a static array is not an lvalue.

For arrays, the argument doesn't have to be ref, because arrays are already a reference type. But for general ranges, you have to require ref, since you don't know if the range is a reference type or not. But requiring ref means you can't pass a slice to the function. If you have a good solution to this conundrum I'm all ears.

@schveiguy
Copy link
Member

The problem is that slice doesn't work because nextPermutation expects a ref argument, and a slice of a static array is not an lvalue.

That doesn't make sense. Why does it need to be an lvalue? If we can remove that requirement, have we fixed this issue?

@quickfur
Copy link
Member Author

We need the argument to be ref for value-type ranges, and non-ref for reference-type ranges, because the function needs to mutate the range.

@schveiguy
Copy link
Member

What's a "value-type" range?

@schveiguy
Copy link
Member

Actually, nevermind. I'll put it this way: If nextPermutation(arr[]) doesn't work, then it's broken. Plain and simple. I thought this pull was a shortcut for that.

@schveiguy
Copy link
Member

We need to fix nextPermutation so it works on rvalue array slices. This is what any person would expect, especially one used to C++'s iterators.

@schveiguy schveiguy closed this Oct 31, 2014
@DmitryOlshansky
Copy link
Member

@quickfur Ehm I guess just require range to have l-value elements, why would something else be needed?

@schveiguy
Copy link
Member

just require range to have l-value elements

Yes, exactly. The range itself does not need to be updated, just its elements.

@quickfur
Copy link
Member Author

Submitted alternative fix.

@jmdavis
Copy link
Member

jmdavis commented Nov 3, 2014

IMHO, we should never make a range-based function accept static arrays. The correct thing to do is require that the static array be sliced, and if that doesn't work with the function for some reason, then we need to look at whether it even makes sense for it to accept a slice (if it does, make that work; if it doesn't, then don't make it work with static arrays). In this case, it sounds like making the function accept array slices makes sense, but regardless, we're just asking for it if we make a range-based function accept a static array. They're not ranges.

@quickfur
Copy link
Member Author

quickfur commented Nov 3, 2014

Yeah, in retrospect that was a bad move. But the alternative fix is simply to allow array slices, which allows the user to pass a slice to a static array where necessary, so that should suffice.

@schveiguy
Copy link
Member

Yeah, in retrospect that was a bad move.

I apologize also for letting it go so far and asking for updates to unit tests etc without realizing what this was actually for.

@quickfur
Copy link
Member Author

quickfur commented Nov 3, 2014

No problem, Dmitry caught it and stopped it in time. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants