View mode: basic / threaded / horizontal-split · Log in · Help
March 29, 2012
Where does "U" in Rebindable.Rebindable come from?
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;
        }
    }
}
March 29, 2012
Re: Where does "U" in Rebindable.Rebindable come from?
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);
}
March 29, 2012
Re: Where does "U" in Rebindable.Rebindable come from?
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
March 29, 2012
Re: Where does "U" in Rebindable.Rebindable come from?
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.
March 30, 2012
Re: Where does "U" in Rebindable.Rebindable come from?
On Fri, 30 Mar 2012 01:09:06 +0200, Simen Kjærås <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, 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.

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..?
March 30, 2012
Re: Where does "U" in Rebindable.Rebindable come from?
On Fri, 30 Mar 2012 15:03:49 +0200, simendsjo <simendsjo@gmail.com> wrote:

> On Fri, 30 Mar 2012 01:09:06 +0200, Simen Kjærås  
> <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, 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.
>
> 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 == 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.
March 30, 2012
Re: Where does "U" in Rebindable.Rebindable come from?
On Fri, 30 Mar 2012 17:13:25 +0200, Simen Kjærås <simen.kjaras@gmail.com>  
wrote:
>
> 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 == 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.

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?
March 30, 2012
Re: Where does "U" in Rebindable.Rebindable come from?
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? They added 'is(XXX, YYY...)'?
March 30, 2012
Re: Where does "U" in Rebindable.Rebindable come from?
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.)
March 31, 2012
Re: Where does "U" in Rebindable.Rebindable come from?
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.
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home