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