digitalmars.D.learn - Where does "U" in Rebindable.Rebindable come from?
- simendsjo (66/66) Mar 29 2012 If you look at the struct, it uses the type U in, among others, the unio...
- Tove (10/23) Mar 29 2012 magic pattern matching...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/31) Mar 29 2012 Some uses of the 'is' expression have been the most magical (read:
- =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= (39/46) Mar 29 2012 Ah, the magic of isExpressions...
-
simendsjo
(11/59)
Mar 30 2012
On Fri, 30 Mar 2012 01:09:06 +0200, Simen Kj=C3=A6r=C3=A5s
- =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= (26/95) Mar 30 2012 =
-
simendsjo
(14/33)
Mar 30 2012
On Fri, 30 Mar 2012 17:13:25 +0200, Simen Kj=C3=A6r=C3=A5s
- =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= (13/45) Apr 01 2012 ays
- Philippe Sigaud (3/8) Mar 30 2012 Wait, does that work now? They added 'is(XXX, YYY...)'?
- Timon Gehr (4/13) Mar 30 2012 The syntax is static if(is(XXX Unused, YYY...)). (Where Unused is
- Philippe Sigaud (2/7) Mar 31 2012 OK, time to update my template tutorial, then.
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
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
On 03/29/2012 01:51 PM, Tove wrote:On Thursday, 29 March 2012 at 20:15:43 UTC, simendsjo wrote: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 AliIf 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
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
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 =t =union. The only place I could see U referenced is in the first static if, bu=sionI 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.e(U), U))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
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 =ut =union. The only place I could see U referenced is in the first static if, b=esionI 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=le(U), U))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
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=ys'yes, there is such a U, so I'll add it to the local scope.'. This mea=nsthat 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=aare 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=utthen 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
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:aysIndeed. The thing is - U is basically *set* by the isExpression. It s=ans'yes, there is such a U, so I'll add it to the local scope.'. This me=iathat 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=eare not met, and as such are defined in the else clause instead of th=butif 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=d =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
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
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:Yes.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?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
On Fri, Mar 30, 2012 at 23:00, Timon Gehr <timon.gehr gmx.ch> wrote:OK, time to update my template tutorial, then.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 31 2012