Idea For Attributes/Annotations

Nick Sabalausky a at a.a
Tue Mar 10 19:42:36 PDT 2009


I've previously voiced my desire for something similar to C#'s attributes 
(annotations in Java, IIRC), but that kind of got sidetracked into a 
discussion of command line parsers. I have another idea of a type of 
scenario where something like this would be very nice, and it also ties into 
the recent complaints of the mixin syntax being ugly.

I just learned over on digitalmars.D.learn that D apparently has no general 
way to convert the value of an enum var to the actual string name of the 
value (at least not without making the underlying type a string containing 
it's own name, but that has obvious drawbacks). To illustrate:

-------------
enum Shape { Square, Circle, Triangle }
Shape s = Shape.Triangle;

// Output is "2", but I want "Shape.Triangle" or "Triangle".
// But there doesn't seem to be a way to do that currently.
Stdout.formatln("{}", s);
-------------

First of all, I would like to propose that we have some built-in way to do 
that. But that's not the main point of this post. The general case I'm 
looking at here is that this is an example of something that can only be 
accomplished (without violating DRY) by using a common mixin pattern: 
Instead of simply declaring what we want, we create and instantiate a mixin 
that generates our intended declaration and also any related boilerplate:

-------------
// Something along these lines...
template generateEnum(char[] name, values...)
{
    const char[] generateEnum = "enum "~name~"{"~/*values*/~"}"~
        "char[] enumToString("~name~" arg) { "~/*big switch(arg) here*/~"}";
}
mixin(generateEnum!("Shape", "Square", "Circle", "Triangle"));
Shape s = Shape.Triangle;
Stdout.formatln("{}", enumToString (s));
-------------

Something along those lines would probably work (in fact, I've done similar 
things before). But, look what a mess that turns the enum's definition into! 
This is probably a good example of what people are thinking of when they 
call the mixin syntax ugly.

So here's my idea: Allow the programmer to attach the desired 
boilerplate-generator to the *actual* definition, instead of generating the 
definition as part of the boilerplate-generator:

-------------
// Actual syntax would probably differ,
// But I'm thinking something along these general lines.

[@GenerateEnumToString("some extra param")]
enum Shape { Square, Circle, Triangle }

// I really haven't throught through the syntax for this part
annotation GenerateEnumToString(T : enum, char[] extraStuff)
{
    const char[] func = "char[] enumToString("~name~" arg) { "~
        /*big switch(arg) here, using compile-time reflection on T*/
    ~"}";
    mixin(func);
}
Shape s = Shape.Triangle;
Stdout.formatln("{}", enumToString (s));
-------------

This way, we could do all the fancy mixin trickery we normally do, but in 
any case where something like this would be applicable, it wouldn't make the 
code look so terrible.





More information about the Digitalmars-d mailing list