alias to a property as an argument to a mixin template

comco void.unsigned at gmail.com
Sun Sep 23 14:45:17 PDT 2012


On Sunday, 23 September 2012 at 21:42:54 UTC, comco wrote:
> On Sunday, 23 September 2012 at 19:53:26 UTC, Philippe Sigaud 
> wrote:
>> monarch_dodra already answered, but since, I typed this, I may 
>> as well
>> post it :)
>>
>>
>> On Sun, Sep 23, 2012 at 8:49 PM, comco 
>> <void.unsigned at gmail.com> wrote:
>>> For this program I'm getting an "Error: need 'this' to access 
>>> member x" at
>>> line (*). Does that mean that we cannot alias a property as 
>>> an argument of a
>>> template mixin?
>>
>> By using s.x, you're not referencing the property, but 
>> directly the
>> value s.x, which is known only at runtime: it cannot be a 
>> template
>> argument.
>>
>> If x where a static member, you could probably use it, hence 
>> the error
>> message (need 'this', ...).
>>
>>> So, using string mixins works, but explicit alias to the 
>>> property name seems
>>> not to. Why is that?
>>
>> a.stringof can be obtained for any symbol a, so s.x (or 
>> with(s) ... x)
>> just gives "s.x", which can be mixed in. It's transformed into 
>> a
>> string, transformation for which there is no need for 'this'.
>>
>>> and is there any other way of achieving the result
>>> witout using template mixins
>>
>> Sorry but... what result? Referencing a member inside a 
>> template?
>> Remember templates can be in another module, written years 
>> ago. If you
>> really want a template to act on a local value, either use a 
>> mixin
>> template, as you did, or reference the member by its name as a 
>> string:
>>
>> import std.stdio;
>>
>> mixin template T(string member)
>> {
>>    void f()
>>    {
>>        mixin("writeln(" ~ member ~ ");");
>>    }
>> }
>>
>> struct S
>> {
>>    int x;
>> }
>>
>> void main() {
>>    auto s = S(4);
>>
>>    mixin T!("s.x");
>>    f();
>>
>> } // prints 4
>>
>> I see monarch proposed exactly the same way to do it...
>
> Thank you for the answers. Passing a string does the job, but 
> the result I wanted to achieve is: the client of the mixin 
> template to use it without strings. Here's the motivating 
> example: when implementing algorithms for linked data 
> structures, a common pattern is such a chain of assignments:
> a1 = a2; a2 = a3; a3 = a4 ...
> For example, take a rotation of a binary tree:
>
>     struct node {
>         node* left, right;
>     }
>
>     void rotate(node* u) {
>         auto v = u.right;
>         u.right = v.left;
>         v.left = u;
>     }
>
> For this pattern, we may design a template function like this:
>
>     void reassign(A...)(ref A a) {
>         static if (A.length > 1) {
>             a[0] = a[1];
>             reassign(a[1 .. $]);
>         }
>     }
>
> Now we can implement our rotate in terms of reassign:
>
>     void rotate(node* u) {
>         auto v = u.right;
>         reassign(u.right, v.left, u);
>     }
>
> This works and is general enough, but notice the duplication of 
> u.right. I don't like it - this may become an arbitrary large 
> expression.
> But the naive attempt fails:
>
>     void rotate(node* u) {
>         node* v;
>         reassign(v, u.right, v.left, u); // runtime error at 
> v.left
>     }
>
> That's because v is not initialized when we call the function. 
> So what we really want is to pass a list of symbols (and I 
> thought `v.left` qualifies as a symbol) to the function, not 
> references to value. But this means we'll need template mixins, 
> because you can pass symbols by alias to them. Since alias 
> arguments for templates are classified as symbolic arguments, I 
> was expecting that you can pass "u.right" as an atomic symbol, 
> without using strings. So, then my strange rotate would look 
> like this:
>
>     void rotate(node* u) {
>         node* v;
>         mixin ReassignMixin!(v, u.right, v.left, u);
>         reassign();
>     }
>
> See how the client code looks nicer when the template arguments 
> are not wrapped as strings.
> So, I thought of template mixins as a too-much-as-macros as 
> they are.
>
> Still, why is `u` "more symbolic" than, say `u.left

Sorry for the last line.


More information about the Digitalmars-d-learn mailing list