www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Swap front for char[] input ranges

reply RazvanN <razvan.nitu1305 gmail.com> writes:
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?
Dec 19 2016
next sibling parent Basile B. <b2.temp gmx.com> writes:
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.
Dec 19 2016
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Dec 19 2016
parent reply RazvanN <razvan.nitu1305 gmail.com> writes:
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
Dec 19 2016
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Dec 19 2016
parent RazvanN <razvan.nitu1305 gmail.com> writes:
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
Dec 21 2016