Just one more thing...

Daniel Keep daniel.keep.lists at gmail.com
Tue Mar 3 02:34:51 PST 2009



Max Samukha wrote:
> On Tue, 03 Mar 2009 20:05:28 +1100, Daniel Keep
> <daniel.keep.lists at gmail.com> wrote:
> 
>>
>> Bill Baxter wrote:
>>> On Mon, Mar 2, 2009 at 11:55 AM, Daniel Keep
>>> <daniel.keep.lists at gmail.com> wrote:
>>>> Frits van Bommel wrote:
>>>>> Sean Kelly wrote:
>>>>>> Daniel Keep wrote:
>>>>>>> extern(C) void __identifier("blah$UNIX2003")(int);
>>>>>> That would be awesome.
>>>>>>
>>>>>>> A beneficial side-effect is that I can finally get rid of all those
>>>>>>> mixins that are just doing this:
>>>>>>>
>>>>>>> mixin(`void `~name_of_fn~`(int a)
>>>>>>> {
>>>>>>>     // ... rest of function ...
>>>>>>> }`);
>>> I'm sure you've thought of this, so why can you not do
>>>    mixin(`void `~name_of_fn~`(int a) { implementation_of_function(a); }`);
>>> or
>>>    mixin(`alias implementation_of_function `~name_of_fn~`);
>> Simple enough to break:
>>
>> mixin(Property("foo", int));
>> mixin(Property("bar", float));
>>
>> You can't use alias.  You have to have some way of generating unique
>> symbol names in a context you don't have any control over. 
> 
> As of 1.039, it seems to be possible to generate unique symbols in a
> reasonable way (not well tested):
> 
> template UniqueAlias(string member, string idName, int id = 0)
> {
>     static if (is(typeof(mixin("this." ~ idName ~ ToString!(id)))))
>         mixin UniqueAlias!(member, idName, id + 1);
>     else
>         mixin("alias " ~ member ~ " " ~ idName ~ ToString!(id) ~ ";");
> }
> 
> unittest
> {
>     class A
>     {
>         int x;
>     }
>     
>     class B : A
>     {
>         int y;
>         void foo() {}
>             
>         template Bar() {}
> 
>         mixin UniqueAlias!("x", "m");
>         mixin UniqueAlias!("y", "m");
>         mixin UniqueAlias!("x", "m");
>         mixin UniqueAlias!("foo", "m");
>         mixin UniqueAlias!("Bar", "m");
>     }
> 
>     auto s = new B;
>     s.m0 = 1;
>     s.m1 = 2;
>     assert(s.x == 1);
>     assert(s.y == 2);
>     assert(s.m2 == 1);
>     s.m3();   
>     alias B.m4!() bar;
> }
> 
>> There are also little issues with this like how the name of the function, when
>> debugging, won't be what you expect it to be.
>>
>> No, you can't use templates because you can't mixin functions with
>> non-public protection with templates.
>>
>>  -- Daniel

Yes, this is definitely an improvement...

char[] Foo(char[] name)
{
    const char[] uid = createUniqueAlias(name);

    return
        `private void `~uid~`() { blah; }`
      ~ `private alias `~uid~` `~name~`;`;
}

class Bar
{
    mixin(Foo("baz"));
}

Wait, no; that won't work.  createUniqueAlias won't have access to the
enclosing scope.  I'll have to do this:

char[] Foo(char[] name)
{
    return `
        mixin CreateUniqueAlias!("uid");

        mixin("private void "~uid~"() { blah; }");

        mixin("private alias "~uid~" `~name`;");
    `;
}

class Bar
{
    mixin(Foo("baz"));
}

Now I get TWO string-escaped mixins AND a meaninglessly named function
mixed into my instantiating code's scope!  Plus, since I need to refer
to the unique name, I have to store it somewhere... and now THAT can
collide with other symbols!

I'm not saying it's not a neat trick; I've used the exact same thing a
few times.  But it's not a solution to *this* problem.

  -- Daniel


More information about the Digitalmars-d-announce mailing list