www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Where does "U" in Rebindable.Rebindable come from?

reply simendsjo <simendsjo gmail.com> writes:
If you look at the struct, it uses the type U in, among others, the union.

The only place I could see U referenced is in the first static if, but I  
cannot recreate this behavior:
void main() {
     static if(is(int X == const(U), U))
     {
     }
     else
     {
         static assert(is(typeof(U))); // false, U not defined
     }
}


And std.typecons.Rebindable:

template Rebindable(T) if (is(T == class) || is(T == interface) ||  
isArray!(T))
{
     static if (!is(T X == const(U), U) && !is(T X == immutable(U), U))
     {
         alias T Rebindable;
     }
     else static if (isArray!(T))
     {
         alias const(ElementType!(T))[] Rebindable;
     }
     else
     {
         struct Rebindable
         {
             private union
             {
                 T original;
                 U stripped;
             }
             void opAssign(T another) pure nothrow
             {
                 stripped = cast(U) another;
             }
             void opAssign(Rebindable another) pure nothrow
             {
                 stripped = another.stripped;
             }
             static if (is(T == const U))
             {
                 // safely assign immutable to const
                 void opAssign(Rebindable!(immutable U) another) pure  
nothrow
                 {
                     stripped = another.stripped;
                 }
             }

             this(T initializer) pure nothrow
             {
                 opAssign(initializer);
             }

              property ref T get() pure nothrow
             {
                 return original;
             }
              property ref const(T) get() const pure nothrow
             {
                 return original;
             }

             alias get this;
         }
     }
}
Mar 29 2012
next sibling parent reply "Tove" <tove fransson.se> writes:
On Thursday, 29 March 2012 at 20:15:43 UTC, simendsjo wrote:
 If you look at the struct, it uses the type U in, among others, 
 the union.

 The only place I could see U referenced is in the first static 
 if, but I cannot recreate this behavior:
 void main() {
     static if(is(int X == const(U), U))
     {
     }
     else
     {
         static assert(is(typeof(U))); // false, U not defined
     }
 }

magic pattern matching... import std.stdio; void main() { static if(is(int x == const(U), U)) writeln("Mutable: " ~ U.stringof); else static if(is(const int x == const(U), U)) writeln("Const: " ~ U.stringof); }
Mar 29 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/29/2012 01:51 PM, Tove wrote:
 On Thursday, 29 March 2012 at 20:15:43 UTC, simendsjo wrote:
 If you look at the struct, it uses the type U in, among others, the
 union.

 The only place I could see U referenced is in the first static if, but
 I cannot recreate this behavior:
 void main() {
 static if(is(int X == const(U), U))
 {
 }
 else
 {
 static assert(is(typeof(U))); // false, U not defined
 }
 }

magic pattern matching... import std.stdio; void main() { static if(is(int x == const(U), U)) writeln("Mutable: " ~ U.stringof); else static if(is(const int x == const(U), U)) writeln("Const: " ~ U.stringof); }

Some uses of the 'is' expression have been the most magical (read: difficult) part of D for me. :) I am still not sure that I understand it correctly. ;) http://dlang.org/expression.html#IsExpression Ali
Mar 29 2012
prev sibling next sibling parent reply =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Thu, 29 Mar 2012 22:15:41 +0200, simendsjo <simendsjo gmail.com> wrote:

 If you look at the struct, it uses the type U in, among others, the  
 union.

 The only place I could see U referenced is in the first static if, but I  
 cannot recreate this behavior:
 void main() {
      static if(is(int X == const(U), U))

Ah, the magic of isExpressions... What happens here is the isExpression asks 'if X is an int, does it match the pattern const(U), where U is some type?' Of course, there is no U for which const(U) == int, so the isExpresion returns false, and your static assert triggers.
     static if (!is(T X == const(U), U) && !is(T X == immutable(U), U))

Again, 'is there a U such that const(U) == T?', then the same for immutable(U). In other words - 'is T mutable?'. The reason the U is there is to explain to the compiler that we're talking about this specific U, not some other U that may be defined elsewhere in the program. The same pattern is used in std.typecons.isTuple: template isTuple(T) { static if (is(Unqual!T Unused : Tuple!Specs, Specs...)) { enum isTuple = true; } else { enum isTuple = false; } } It can also be extended to other templates: struct Foo() {} struct Foo(int n) {} struct Foo(T) {} template FooType(T) { static if (is(Unqual!T Unused : Foo!())) { enum FooType = "Type 1"; } else static if (is(Unqual!T Unused : Foo!n, int n)) { enum FooType = "Type 2"; } else static if (is(Unqual!T Unused : Foo!U, U)) { enum FooType = "Type 3"; } else { enum FooType = "No Foo!"; } } Hope this helps.
Mar 29 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/30/2012 09:20 PM, Philippe Sigaud wrote:
 On Fri, Mar 30, 2012 at 01:09, Simen Kjærås<simen.kjaras gmail.com>  wrote:
 The same pattern is used in std.typecons.isTuple:

 template isTuple(T)
 {
     static if (is(Unqual!T Unused : Tuple!Specs, Specs...))
     {

Wait, does that work now?

Yes.
 They added 'is(XXX, YYY...)'?

The syntax is static if(is(XXX Unused, YYY...)). (Where Unused is something you never have any use for.)
Mar 30 2012
prev sibling next sibling parent simendsjo <simendsjo gmail.com> writes:
On Fri, 30 Mar 2012 01:09:06 +0200, Simen Kj=C3=A6r=C3=A5s <simen.kjaras=
 gmail.com>  =

wrote:

 On Thu, 29 Mar 2012 22:15:41 +0200, simendsjo <simendsjo gmail.com>  =

 wrote:

 If you look at the struct, it uses the type U in, among others, the  =


 union.

 The only place I could see U referenced is in the first static if, bu=


 I cannot recreate this behavior:
 void main() {
      static if(is(int X =3D=3D const(U), U))

Ah, the magic of isExpressions... What happens here is the isExpression asks 'if X is an int, does it match the pattern const(U), where U is some type?' Of course, there is no U for which const(U) =3D=3D int, so the isExpre=

 returns false, and your static assert triggers.


     static if (!is(T X =3D=3D const(U), U) && !is(T X =3D=3D immutabl=


 Again, 'is there a U such that const(U) =3D=3D T?', then the same for
 immutable(U). In other words - 'is T mutable?'.

 The reason the U is there is to explain to the compiler that we're
 talking about this specific U, not some other U that may be defined
 elsewhere in the program.

 The same pattern is used in std.typecons.isTuple:

 template isTuple(T)
 {
      static if (is(Unqual!T Unused : Tuple!Specs, Specs...))
      {
          enum isTuple =3D true;
      }
      else
      {
          enum isTuple =3D false;
      }
 }

 It can also be extended to other templates:

 struct Foo() {}
 struct Foo(int n) {}
 struct Foo(T) {}

 template FooType(T) {
      static if (is(Unqual!T Unused : Foo!())) {
          enum FooType =3D "Type 1";
      } else static if (is(Unqual!T Unused : Foo!n, int n)) {
          enum FooType =3D "Type 2";
      } else static if (is(Unqual!T Unused : Foo!U, U)) {
          enum FooType =3D "Type 3";
      } else {
          enum FooType =3D "No Foo!";
      }
 }


 Hope this helps.

Look at the Rebindable example again. What I don't understand is how U c= an = be defined in the else block. Like your example here. "Unused" isn't defined in the else block, right.= .?
Mar 30 2012
prev sibling next sibling parent =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Fri, 30 Mar 2012 15:03:49 +0200, simendsjo <simendsjo gmail.com> wrot=
e:

 On Fri, 30 Mar 2012 01:09:06 +0200, Simen Kj=C3=A6r=C3=A5s  =

 <simen.kjaras gmail.com> wrote:

 On Thu, 29 Mar 2012 22:15:41 +0200, simendsjo <simendsjo gmail.com>  =


 wrote:

 If you look at the struct, it uses the type U in, among others, the =



 union.

 The only place I could see U referenced is in the first static if, b=



 I cannot recreate this behavior:
 void main() {
      static if(is(int X =3D=3D const(U), U))

Ah, the magic of isExpressions... What happens here is the isExpression asks 'if X is an int, does it match the pattern const(U), where U is some type?' Of course, there is no U for which const(U) =3D=3D int, so the isExpr=


 returns false, and your static assert triggers.


     static if (!is(T X =3D=3D const(U), U) && !is(T X =3D=3D immutab=



 Again, 'is there a U such that const(U) =3D=3D T?', then the same for=


 immutable(U). In other words - 'is T mutable?'.

 The reason the U is there is to explain to the compiler that we're
 talking about this specific U, not some other U that may be defined
 elsewhere in the program.

 The same pattern is used in std.typecons.isTuple:

 template isTuple(T)
 {
      static if (is(Unqual!T Unused : Tuple!Specs, Specs...))
      {
          enum isTuple =3D true;
      }
      else
      {
          enum isTuple =3D false;
      }
 }

 It can also be extended to other templates:

 struct Foo() {}
 struct Foo(int n) {}
 struct Foo(T) {}

 template FooType(T) {
      static if (is(Unqual!T Unused : Foo!())) {
          enum FooType =3D "Type 1";
      } else static if (is(Unqual!T Unused : Foo!n, int n)) {
          enum FooType =3D "Type 2";
      } else static if (is(Unqual!T Unused : Foo!U, U)) {
          enum FooType =3D "Type 3";
      } else {
          enum FooType =3D "No Foo!";
      }
 }


 Hope this helps.

Look at the Rebindable example again. What I don't understand is how U=

 can be defined in the else block.
 Like your example here. "Unused" isn't defined in the else block,  =

 right..?

Indeed. The thing is - U is basically *set* by the isExpression. It says= 'yes, there is such a U, so I'll add it to the local scope.'. This means= that U will be set for the entire scope within which the static if exists. Due to the way the criteria are phrased, U is defined when the criteria are not met, and as such are defined in the else clause instead of the if clause. { // Outer scope starts here. static if ( !is( const(int) t =3D=3D const(U), U ) ) { // isExpression returned false, so U is undefined } else { // But here it is defined, because we're still in the same, // broader scope. } } // And here it's no longer defined. Was that any better? I admit I didn't understand it at first either, but= then I remembered that static if does not introduce a new scope. That helped.
Mar 30 2012
prev sibling next sibling parent simendsjo <simendsjo gmail.com> writes:
On Fri, 30 Mar 2012 17:13:25 +0200, Simen Kj=C3=A6r=C3=A5s <simen.kjaras=
 gmail.com>  =

wrote:
 Indeed. The thing is - U is basically *set* by the isExpression. It sa=

 'yes, there is such a U, so I'll add it to the local scope.'. This mea=

 that U will be set for the entire scope within which the static if
 exists.

 Due to the way the criteria are phrased, U is defined when the criteri=

 are not met, and as such are defined in the else clause instead of the=

 if clause.


 { // Outer scope starts here.
    static if ( !is( const(int) t =3D=3D const(U), U ) ) {
      // isExpression returned false, so U is undefined
    } else {
      // But here it is defined, because we're still in the same,
      // broader scope.
    }
 }
 // And here it's no longer defined.

 Was that any better? I admit I didn't understand it at first either, b=

 then I remembered that static if does not introduce a new scope. That
 helped.

I knew static if didn't create a new scope, but I still thought U would = = not be defined if it didn't match, but it seems it is defined just by = existing in the scope. I had a bug when I tried to reproduce the behavior: I used typeof(U), = which is, of course, not possible as U is a type :) Thanks for the explanation. Allowed to use D at work yet btw?
Mar 30 2012
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Fri, Mar 30, 2012 at 01:09, Simen Kj=C3=A6r=C3=A5s <simen.kjaras gmail.c=
om> wrote:
 The same pattern is used in std.typecons.isTuple:

 template isTuple(T)
 {
 =C2=A0 =C2=A0static if (is(Unqual!T Unused : Tuple!Specs, Specs...))
 =C2=A0 =C2=A0{

Wait, does that work now? They added 'is(XXX, YYY...)'?
Mar 30 2012
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Fri, Mar 30, 2012 at 23:00, Timon Gehr <timon.gehr gmx.ch> wrote:
 Wait, does that work now?

Yes.
 They added 'is(XXX, YYY...)'?

The syntax is static if(is(XXX Unused, YYY...)). (Where Unused is something you never have any use for.)

OK, time to update my template tutorial, then.
Mar 31 2012
prev sibling parent =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Fri, 30 Mar 2012 19:52:50 +0200, simendsjo <simendsjo gmail.com> wrot=
e:

 On Fri, 30 Mar 2012 17:13:25 +0200, Simen Kj=C3=A6r=C3=A5s  =

 <simen.kjaras gmail.com> wrote:
 Indeed. The thing is - U is basically *set* by the isExpression. It s=


 'yes, there is such a U, so I'll add it to the local scope.'. This me=


 that U will be set for the entire scope within which the static if
 exists.

 Due to the way the criteria are phrased, U is defined when the criter=


 are not met, and as such are defined in the else clause instead of th=


 if clause.


 { // Outer scope starts here.
    static if ( !is( const(int) t =3D=3D const(U), U ) ) {
      // isExpression returned false, so U is undefined
    } else {
      // But here it is defined, because we're still in the same,
      // broader scope.
    }
 }
 // And here it's no longer defined.

 Was that any better? I admit I didn't understand it at first either, =


 then I remembered that static if does not introduce a new scope. That=


 helped.

I knew static if didn't create a new scope, but I still thought U woul=

 not be defined if it didn't match, but it seems it is defined just by =

 existing in the scope.
 I had a bug when I tried to reproduce the behavior: I used typeof(U), =

 which is, of course, not possible as U is a type :)

 Thanks for the explanation. Allowed to use D at work yet btw?

Not really. I use it a lot for scripts and fast prototyping, but it's not the most flexible of organizations. Could use it for internal tools,= likely.
Apr 01 2012