Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
December 19, 2016 Swap front for char[] input ranges | ||||
---|---|---|---|---|
| ||||
Hi, I have a function which accepts 2 input Ranges and swaps the first element in Range1 with the first element in Range2. The swapping code looks something like this : static if (is(typeof(swap(r1.front, r2.front)))) { swap(r1.front, r2.front); } else { auto t1 = moveFront(r1), t2 = moveFront(r2); auto tmp1 = r1.front; auto tmp2 = r2.front; r1.front = move(t2); r2.front = move(t1); } This code works for most cases, except when 2 char[] are passed. In that case, the compilation fails with error messages which state that r1.front and r2.front are not Lvalues. So, my question is: how can I swap the 2 elements since in the case of char[] input ranges the front property does not return a reference? |
December 19, 2016 Re: Swap front for char[] input ranges | ||||
---|---|---|---|---|
| ||||
Posted in reply to RazvanN | On Monday, 19 December 2016 at 10:41:46 UTC, RazvanN wrote:
> Hi,
>
> I have a function which accepts 2 input Ranges and swaps the first element in Range1 with the first element in Range2. The swapping code looks something like this :
>
> static if (is(typeof(swap(r1.front, r2.front))))
> {
> swap(r1.front, r2.front);
> }
> else
> {
> auto t1 = moveFront(r1), t2 = moveFront(r2);
> auto tmp1 = r1.front;
> auto tmp2 = r2.front;
> r1.front = move(t2);
> r2.front = move(t1);
> }
>
> This code works for most cases, except when 2 char[] are passed.
> In that case, the compilation fails with error messages which state
> that r1.front and r2.front are not Lvalues. So, my question is:
> how can I swap the 2 elements since in the case of char[] input ranges
> the front property does not return a reference?
does it work if you cast the 2 char[] as 2 ubyte[] ?
If so, it's a problem with narrow strings and utf8 decoding...i.e there's no guarantee that each code unit in r1 matches to a code unit in r2.
|
December 19, 2016 Re: Swap front for char[] input ranges | ||||
---|---|---|---|---|
| ||||
Posted in reply to RazvanN | On 12/19/2016 02:41 AM, RazvanN wrote: > Hi, > > I have a function which accepts 2 input Ranges As your comments make it clear below, they cannot be InputRanges. > and swaps the first > element in Range1 with the first element in Range2. The swapping code > looks something like this : > > static if (is(typeof(swap(r1.front, r2.front)))) > { > swap(r1.front, r2.front); > } > else > { > auto t1 = moveFront(r1), t2 = moveFront(r2); > auto tmp1 = r1.front; > auto tmp2 = r2.front; Obivously, tmp1 and tmp2 are unusued there. :) > r1.front = move(t2); > r2.front = move(t1); > } > > This code works for most cases, except when 2 char[] are passed. > In that case, the compilation fails with error messages which state > that r1.front and r2.front are not Lvalues. So, my question is: > how can I swap the 2 elements since in the case of char[] input ranges > the front property does not return a reference? Not possible... It's ok to use something similar to the following template constraint: void foo(R1, R2)(R1 r1, R2 r2) if ((hasSwappableElements!R1 && hasSwappableElements!R2) || (hasLvalueElements!R1 && hasLvalueElements!R2)) { // ... } Ali |
December 19, 2016 Re: Swap front for char[] input ranges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Monday, 19 December 2016 at 12:25:02 UTC, Ali Çehreli wrote: > On 12/19/2016 02:41 AM, RazvanN wrote: > > [...] > > As your comments make it clear below, they cannot be InputRanges. > > > [...] > swapping code > > [...] > > Obivously, tmp1 and tmp2 are unusued there. :) > > > [...] > passed. > > [...] > state > > [...] > is: > > [...] > input ranges > > [...] > > Not possible... It's ok to use something similar to the following template constraint: > > void foo(R1, R2)(R1 r1, R2 r2) > if ((hasSwappableElements!R1 && hasSwappableElements!R2) || > (hasLvalueElements!R1 && hasLvalueElements!R2)) { > // ... > } > > Ali In this case, the bringToFront function [1] should not accept char[] as parameters? Or a special path should be added in the function, so that char[] are treated specially? [1] http://dlang.org/phobos/std_algorithm_mutation.html#bringToFront |
December 19, 2016 Re: Swap front for char[] input ranges | ||||
---|---|---|---|---|
| ||||
Posted in reply to RazvanN | On 12/19/2016 06:09 AM, RazvanN wrote: > On Monday, 19 December 2016 at 12:25:02 UTC, Ali Çehreli wrote: >> On 12/19/2016 02:41 AM, RazvanN wrote: >> > [...] >> >> As your comments make it clear below, they cannot be InputRanges. >> >> > [...] >> swapping code >> > [...] >> >> Obivously, tmp1 and tmp2 are unusued there. :) >> >> > [...] >> passed. >> > [...] >> state >> > [...] >> is: >> > [...] >> input ranges >> > [...] >> >> Not possible... It's ok to use something similar to the following >> template constraint: >> >> void foo(R1, R2)(R1 r1, R2 r2) >> if ((hasSwappableElements!R1 && hasSwappableElements!R2) || >> (hasLvalueElements!R1 && hasLvalueElements!R2)) { >> // ... >> } >> >> Ali > > In this case, the bringToFront function [1] should not accept char[] > as parameters? Or a special path should be added in the function, so > that char[] are treated specially? > > [1] http://dlang.org/phobos/std_algorithm_mutation.html#bringToFront First, thanks to you and to your colleagues very much for improving D with these fixes. :) I think you're working on the following bug: https://issues.dlang.org/show_bug.cgi?id=16959 Regarding the compilation error inside swapFront, its template constraints should be fixed as I suggested earlier. It cannot work with any two InputRanges. I think it warrants its separate bug. private void swapFront(R1, R2)(R1 r1, R2 r2) if (isInputRange!R1 && isInputRange!R2) { static if (is(typeof(swap(r1.front, r2.front)))) { swap(r1.front, r2.front); } else { auto t1 = moveFront(r1), t2 = moveFront(r2); r1.front = move(t2); r2.front = move(t1); } } Regarding bringToFront: 1) Reading its documentation, bringToFront() seems to be an algorithms that mutates its ranges (not just give a brought-to-front view of existing data). If so, its argument cannot simply be an InputRange because there are InputRanges out there where you cannot write it their .front. (char[] is just one example.): size_t bringToFront(Range1, Range2)(Range1 front, Range2 back) if (isInputRange!Range1 && isForwardRange!Range2) { // ... } Its template constraint must also be changed to include a combination of hasLvalueElements() and hasMobileElements(). 2) After fixing that, a char[] can indeed bring characters to front but it would be an expensive operation where a multi-byte Unicode character would necessarily move a single-byte Unicode character to the right. (Additionally, depending on its length, the first argument may allow only a partial UTF-8 encoding at its end. Fail! :) ) I don't know how to allow or encode such an expensive operation which is outside the documented "Ο(max(front.length, back.length))" complexity of bringToFront(). If it were me, I would look for possibilities to change the behavior and make bringToFront() a non-mutating algorithm. What do others think? Ali |
December 21, 2016 Re: Swap front for char[] input ranges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Monday, 19 December 2016 at 20:26:26 UTC, Ali Çehreli wrote: > On 12/19/2016 06:09 AM, RazvanN wrote: > > [...] > wrote: > >> [...] > InputRanges. > >> [...] > following > > [...] > char[] > > [...] > function, so > > [...] > http://dlang.org/phobos/std_algorithm_mutation.html#bringToFront > > [...] No need to mention it. It is an honor to be able contribute to this great language. > > [...] That is right, I am working on that particular bug. After talking with AndreiA, I submitted this PR [1]. It treats the case of char[], but I am not really sure how the constraints should be applied to the function since it seems there are a lot of combinations (especially if char[] is supported). [1] https://github.com/dlang/phobos/pull/4970 |
Copyright © 1999-2021 by the D Language Foundation