Just one more thing...

Max Samukha samukha at voliacable.com.removethis
Tue Mar 3 04:47:18 PST 2009


On Tue, 03 Mar 2009 21:34:51 +1100, Daniel Keep
<daniel.keep.lists at gmail.com> wrote:

>
>
>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. 

Yes, the mixin that checks for uniqueness needs to have access to the
scope where it is instantiated. So it has to be mixed in directly or
as part of another template mixin

> 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

I didn't say it's a solution to this problem. I was saying it is
possible to generate unique symbol names. Your problem could be solved
like this:

template Property(string name, T)
{
    private T _prop;
    private T prop()
    {
       return _prop;
    }
    private T prop(T v)
    {
       _prop = v;
        return v;
    }

    mixin ("alias prop " ~ name ~ ";");
}

class A
{
    mixin Property!("foo", int);
}

class B : A
{
    mixin Property!("bar", float);
    mixin Property!("baz", int);
}

void main()
{
    auto b = new B;
    b.foo = 1;
    b.bar = 2.0;
    b.baz = 3;

    assert (b.foo == 1);
    assert (b.bar == 2.0);
    assert (b.baz == 3);
}

But such properties cannot implement interfaces. The spec says nothing
about whether aliases should be able to implement interface functions,
so I'm not sure if it's a compiler bug.

Ok, I'm all for the ident() thing. Or probably 'mixin' can be reused?
What ambiguities may arise?

void mixin("foo")() {}







More information about the Digitalmars-d-announce mailing list