www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Eliminate redundancy of dup/idup

reply kenji hara <k.hara.pg gmail.com> writes:
I've posted two pull requests for the purpose.

https://github.com/D-Programming-Language/dmd/pull/1110
https://github.com/D-Programming-Language/druntime/pull/298

inout parameter and strongly purity function can realize this.

Details:

The new dup function's signature is:

auto dup(E)(inout(E)[] arr) pure  trusted;

If E has some mutable indirections (class, struct has mutable
pointers, array, etc),
dup would return inout(E). And the purity of dup function is
calculated to 'constant purity'.
Then the elements of returned value keep original type modifier.

    class C {}
    struct S { int* ptr; }

    C[] carr;
    S[] sarr;
    int[][] aarr;
    static assert(is(typeof(dup(carr)) == C[]));
    static assert(is(typeof(dup(sarr)) == S[]));
    static assert(is(typeof(dup(aarr)) == int[][]));

If E does not have mutable indirection (built-in types, struct don't
have pointers, etc),
dup would return E[]. And the purity of dup function is calculated to
'strong purity'.
Then returned value can be implicitly convertible to immutable(E[]).

    struct S { long value; }

    S[] sarr;
    int[] narr;
    static assert(is(typeof(dup(sarr)) == S[]));
    static assert(is(typeof(dup(parr)) == int*[]));
    immutable S[] isarr = dup(sarr);    // allowed!
    immutable int[] inarr = dup(narr);  // allowed!

And today, dup function is used with UFCS.

    int[] marr;
    immutable int[] iarr = marr.dup();

Finally, built-in dup and idup are merged into library dup(). Destroy!

Kenji Hara
Sep 09 2012
next sibling parent "nazriel" <spam dzfl.pl> writes:
On Sunday, 9 September 2012 at 15:32:01 UTC, kenji hara wrote:
 I've posted two pull requests for the purpose.

 https://github.com/D-Programming-Language/dmd/pull/1110
 https://github.com/D-Programming-Language/druntime/pull/298

 inout parameter and strongly purity function can realize this.

 Details:

 The new dup function's signature is:

 auto dup(E)(inout(E)[] arr) pure  trusted;

 If E has some mutable indirections (class, struct has mutable
 pointers, array, etc),
 dup would return inout(E). And the purity of dup function is
 calculated to 'constant purity'.
 Then the elements of returned value keep original type modifier.

     class C {}
     struct S { int* ptr; }

     C[] carr;
     S[] sarr;
     int[][] aarr;
     static assert(is(typeof(dup(carr)) == C[]));
     static assert(is(typeof(dup(sarr)) == S[]));
     static assert(is(typeof(dup(aarr)) == int[][]));

 If E does not have mutable indirection (built-in types, struct 
 don't
 have pointers, etc),
 dup would return E[]. And the purity of dup function is 
 calculated to
 'strong purity'.
 Then returned value can be implicitly convertible to 
 immutable(E[]).

     struct S { long value; }

     S[] sarr;
     int[] narr;
     static assert(is(typeof(dup(sarr)) == S[]));
     static assert(is(typeof(dup(parr)) == int*[]));
     immutable S[] isarr = dup(sarr);    // allowed!
     immutable int[] inarr = dup(narr);  // allowed!

 And today, dup function is used with UFCS.

     int[] marr;
     immutable int[] iarr = marr.dup();

 Finally, built-in dup and idup are merged into library dup(). 
 Destroy!

 Kenji Hara

Does anybody told you already that you freaking amazing?! This rox, I've already seen it on GH. Kenji for president++!
Sep 09 2012
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sunday, 9 September 2012 at 15:32:01 UTC, kenji hara wrote:
 Then returned value can be implicitly convertible to 
 immutable(E[]).

What about rebindable with auto? For example: void main() { char[] a = "cool".dup; string b = a.idup; // explicitly immutable(char)[] auto c = a.idup; // automatically typeof(c) == immutable(char)[] c = "another"; // so this compiles } I do this in a few places in my code. If I want it to be immutable(char[]), I'll write immutable instead of auto.
Sep 09 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/09/2012 05:44 PM, kenji hara wrote:
 2012/9/10 Adam D. Ruppe <destructionator gmail.com>:
 On Sunday, 9 September 2012 at 15:32:01 UTC, kenji hara wrote:
 Then returned value can be implicitly convertible to immutable(E[]).

What about rebindable with auto? For example: void main() { char[] a = "cool".dup; string b = a.idup; // explicitly immutable(char)[] auto c = a.idup; // automatically typeof(c) == immutable(char)[]

Yes. In this case, you should write: immutable c = a.dup(); // explicit immutable conversion
          c = "another"; // so this compiles


This does not compile anymore now.
 }


+1 for moving to library and lifting restrictions on conversion. -1 for removing .idup, it is handy.
Sep 09 2012
next sibling parent reply Piotr Szturmaj <bncrbme jadamspam.pl> writes:
Timon Gehr wrote:
 -1 for removing .idup, it is handy.

auto idup(E)(const(E)[] arr) pure trusted { immutable result = arr.dup(); return result; } :-)
Sep 09 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/09/2012 06:37 PM, Piotr Szturmaj wrote:
 Timon Gehr wrote:
 -1 for removing .idup, it is handy.

auto idup(E)(const(E)[] arr) pure trusted { immutable result = arr.dup(); return result; }

auto idup(E)(const(E)[] arr) pure nothrow safe if(is(typeof({immutable r=arr.dup;}))){ return cast()cast(immutable)arr.dup; }
 :-)

Sep 09 2012
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/09/2012 06:33 PM, Adam D. Ruppe wrote:
 On Sunday, 9 September 2012 at 16:25:12 UTC, Timon Gehr wrote:
         c = "another"; // so this compiles


This does not compile anymore now.

One option I've heard that might be OK is to make auto strip off the top level immutable: immutable(char[]) a; auto b = a; // b is immutable(char)[] b = "test"; // allowed This kind of thing is already done on function calls. If you want to keep the full immutability including the top one, use immutable instead of auto.

I am in favour of this change, but why would it help eliminate the usefulness of .idup?
Sep 09 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/09/2012 07:06 PM, kenji hara wrote:
 An advantage of generic dup() is to allow copying of const arrays.

 void main()
 {
      class C {}
      const C[] ca = new C[3];
      //ca.dup;
      // Error: cannot implicitly convert element type const(C) to
 mutable in ca.dup
      //ca.idup;
      // Error: cannot implicitly convert element type const(C) to
 immutable in ca.idup
      ca.dup();
      // result is const(C[])
 }

 ----

 According to what I remember, the name 'idup' had been discussed in
 the beginning of D2, but it had been disappeared from the need for
 idup. But it is still oddly name.

 Using:
    auto iarr = marr.idup;
 Instead of :
    immutable iarr = marr.dup();  // In the future, () would not be necessary

 Is really handy? Yes, it is 6(or 4) characters shorter.  But I can't
 see it *handy*.

What you are missing is that the two code segments are not equivalent.
Sep 09 2012
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
Thanks for quick response.

2012/9/10 nazriel <spam dzfl.pl>:
 Does anybody told you already that you freaking amazing?!
 This rox, I've already seen it on GH.

 Kenji for president++!

Sep 09 2012
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
2012/9/10 Adam D. Ruppe <destructionator gmail.com>:
 On Sunday, 9 September 2012 at 15:32:01 UTC, kenji hara wrote:
 Then returned value can be implicitly convertible to immutable(E[]).

What about rebindable with auto? For example: void main() { char[] a = "cool".dup; string b = a.idup; // explicitly immutable(char)[] auto c = a.idup; // automatically typeof(c) == immutable(char)[]

Yes. In this case, you should write: immutable c = a.dup(); // explicit immutable conversion
         c = "another"; // so this compiles
 }

 I do this in a few places in my code. If I want it to be immutable(char[]),
 I'll write immutable instead of auto.

Kenji Hara
Sep 09 2012
prev sibling next sibling parent "Jesse Phillips" <jessekphillips+D gmail.com> writes:
On Sunday, 9 September 2012 at 15:32:01 UTC, kenji hara wrote:
 Finally, built-in dup and idup are merged into library dup(). 
 Destroy!

 Kenji Hara

Well, that is pretty awesome. I didn't see an example which says this would work, but I expect it would? char[] a = dup("Hello"); string b = dup(a); I'm not as familiar with the pure to immutable but I believe to immutable(char)[] is or should be valid right?
Sep 09 2012
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
Yes, This works just as expected.

import std.stdio;
void main()
{
    char[] a = dup("Hello");
    string b = dup(a);
    writeln(a);  // prints "Hello"
    writeln(b);  // prints "Hello"
    assert(cast(void*)a.ptr !is cast(void*)b.ptr);  // elements are duplicated
}

Kenji Hara

2012/9/10 Jesse Phillips <jessekphillips+D gmail.com>:
 On Sunday, 9 September 2012 at 15:32:01 UTC, kenji hara wrote:
 Finally, built-in dup and idup are merged into library dup(). Destroy!

 Kenji Hara

Well, that is pretty awesome. I didn't see an example which says this would work, but I expect it would? char[] a = dup("Hello"); string b = dup(a); I'm not as familiar with the pure to immutable but I believe to immutable(char)[] is or should be valid right?

Sep 09 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/09/2012 05:32 PM, kenji hara wrote:
 ...
 Then the elements of returned value keep original type modifier.
 ...

Usually .dup or .idup are used to explicitly change the type modifier, and they still allow type deduction. I'd be fine with having .dup be inout, .mdup mutable and .idup immutable.
Sep 09 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/09/2012 06:32 PM, Timon Gehr wrote:
 On 09/09/2012 05:32 PM, kenji hara wrote:
 ...
 Then the elements of returned value keep original type modifier.
 ...

Usually .dup or .idup are used to explicitly change the type modifier, and they still allow type deduction. I'd be fine with having .dup be inout, .mdup mutable and .idup immutable.

Ignore that, I misunderstood.
Sep 09 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sunday, 9 September 2012 at 16:25:12 UTC, Timon Gehr wrote:
         c = "another"; // so this compiles


This does not compile anymore now.

One option I've heard that might be OK is to make auto strip off the top level immutable: immutable(char[]) a; auto b = a; // b is immutable(char)[] b = "test"; // allowed This kind of thing is already done on function calls. If you want to keep the full immutability including the top one, use immutable instead of auto.
Sep 09 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sunday, 9 September 2012 at 16:38:43 UTC, Timon Gehr wrote:
 I am in favour of this change, but why would it help eliminate 
 the usefulness of .idup?

I'm not for the removal of idup.
Sep 09 2012
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
An advantage of generic dup() is to allow copying of const arrays.

void main()
{
    class C {}
    const C[] ca = new C[3];
    //ca.dup;
    // Error: cannot implicitly convert element type const(C) to
mutable in ca.dup
    //ca.idup;
    // Error: cannot implicitly convert element type const(C) to
immutable in ca.idup
    ca.dup();
    // result is const(C[])
}

----

According to what I remember, the name 'idup' had been discussed in
the beginning of D2, but it had been disappeared from the need for
idup. But it is still oddly name.

Using:
  auto iarr = marr.idup;
Instead of :
  immutable iarr = marr.dup();  // In the future, () would not be necessary

Is really handy? Yes, it is 6(or 4) characters shorter. But I can't
see it *handy*.
"idup" is still odd name to me.

Kenji Hara

2012/9/10 Timon Gehr <timon.gehr gmx.ch>:
 On 09/09/2012 05:44 PM, kenji hara wrote:
 2012/9/10 Adam D. Ruppe <destructionator gmail.com>:
 On Sunday, 9 September 2012 at 15:32:01 UTC, kenji hara wrote:

 Then returned value can be implicitly convertible to immutable(E[]).

What about rebindable with auto? For example: void main() { char[] a = "cool".dup; string b = a.idup; // explicitly immutable(char)[] auto c = a.idup; // automatically typeof(c) == immutable(char)[]

Yes. In this case, you should write: immutable c = a.dup(); // explicit immutable conversion
          c = "another"; // so this compiles


This does not compile anymore now.
 }


+1 for moving to library and lifting restrictions on conversion. -1 for removing .idup, it is handy.

Sep 09 2012
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
2012/9/10 Timon Gehr <timon.gehr gmx.ch>:
 On 09/09/2012 07:06 PM, kenji hara wrote:
 An advantage of generic dup() is to allow copying of const arrays.

 void main()
 {
      class C {}
      const C[] ca = new C[3];
      //ca.dup;
      // Error: cannot implicitly convert element type const(C) to
 mutable in ca.dup
      //ca.idup;
      // Error: cannot implicitly convert element type const(C) to
 immutable in ca.idup
      ca.dup();
      // result is const(C[])
 }

 ----

 According to what I remember, the name 'idup' had been discussed in
 the beginning of D2, but it had been disappeared from the need for
 idup. But it is still oddly name.

 Using:
    auto iarr = marr.idup;
 Instead of :
    immutable iarr = marr.dup();  // In the future, () would not be
 necessary

 Is really handy? Yes, it is 6(or 4) characters shorter.  But I can't
 see it *handy*.

What you are missing is that the two code segments are not equivalent.

Hmm, it's right. They are not equivalent. void main() { int[] marr; auto iarr1 = marr.idup; immutable iarr2 = marr.dup(); pragma(msg, typeof(iarr1)); // prints immutable(int)[] pragma(msg, typeof(iarr2)); // prints immutable(int[]) } It's hard problem... Kenji Hara
Sep 09 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
kenji hara:

 I've posted two pull requests for the purpose.

This is something related. Are your recent patches allowing code like this, that are two common needs? void main() { auto a1 = [1, 2]; auto a2 = [3, 4]; immutable a3 = a1 ~ a2; // line 4 immutable a4 = [10, 20]; immutable a5 = [100]; int[] a6 = a4 ~ a5; // line 7 } test.d(4): Error: cannot implicitly convert expression (a1 ~ a2) of type int[] to immutable(int[]) test.d(7): Error: cannot implicitly convert expression (a4 ~ a5) of type immutable(int)[] to int[] Bye, bearophile
Sep 09 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 9/9/12, Adam D. Ruppe <destructionator gmail.com> wrote:
 One option I've heard that might be OK is to make auto strip off
 the top level immutable:

 immutable(char[]) a;
 auto b = a; // b is immutable(char)[]

Sounds like something that could bite you in generic code if you expect 'auto' to do nothing more than type inference. is() expressions might start failing, etc..
Sep 09 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 09 Sep 2012 11:32:10 -0400, kenji hara <k.hara.pg gmail.com> wrote:

 I've posted two pull requests for the purpose.

 https://github.com/D-Programming-Language/dmd/pull/1110
 https://github.com/D-Programming-Language/druntime/pull/298

 inout parameter and strongly purity function can realize this.

Excellent! I have been waiting for this for a long time. -Steve
Sep 10 2012
prev sibling parent "Daniel Murphy" <yebblies nospamgmail.com> writes:
"kenji hara" <k.hara.pg gmail.com> wrote in message 
news:mailman.1679.1347204757.31962.digitalmars-d puremagic.com...
 I've posted two pull requests for the purpose.

 https://github.com/D-Programming-Language/dmd/pull/1110
 https://github.com/D-Programming-Language/druntime/pull/298

 inout parameter and strongly purity function can realize this.

This is great. Is there any chance a similar method could be applied to give '~' and 'new' the same strong-purity benefits? This is much cleaner than introducing expression-level purity.
Sep 10 2012