Proposal: user defined attributes

Kapps opantm2+spam at gmail.com
Fri Mar 16 17:41:17 PDT 2012


On Friday, 16 March 2012 at 16:09:55 UTC, Andrei Alexandrescu 
wrote:
> So we have:
>
> class A {
>     @note(Serializable.yes) int a;
>     ...
> }
>
> vs. a hypothetical in-language solution:
>
> class A {
>     int a;
>     mixin(note("a", Serializable.yes));
>     ...
> }
>
> I wonder to what extent the in-language solution can be made to 
> work.
>
>
> Andrei

This gets to an unreasonable amount of noise and complexity. 
First, you have the issue of using mixins. Using mixins is quite 
ugly. It's very tool unfriendly. It's not easily readable. It can 
mess up line numbers. It may or may not be limited in situations 
such as with parameters.

In language solutions should be preferred for many things, but 
ultimately, not everything is a nail to hammer.

Ultimately, I'd like to see being able to use any CTFE capable 
struct/class for an attribute with a constructor, ideally with 
access to the symbol it's defined on. This allows things like (if 
my unchecked code was correct):

@attribute struct WebForm {
     string FormName;
     this(string FormName) {
         this.FormName = FormName;
         static assert(is(typeof(Symbol) : struct));
         static assert(__traits(getAllMembers, Symbol).length > 0);
         // TODO: Make sure at least one member set to 
Browsable(true).
     }
}

@attribute struct Validate {
     string Pattern;
     this(string Pattern) {
         this.Pattern = Pattern;
         static assert(isValidRegex(Pattern));
     }
}

@WebForm("Account");
@PostTo("Services/CreateAccount")
@SecureOnly(true)
struct CreateAccountForm {

     @Description("The name of your account. Must be between 3 and 
12 letters.");
     @Validate(r"\w{3,12}")
     string Username;

     @Validate(r"\w+@\w+.\w+");
     @Description("The email address to associate with this 
account.");
     string Email;

}

While it's a bit of boiler plate to create the library and 
attributes, you only need to do it once. Then you can make a very 
nice form that automatically validates fields both clientside 
(where JS and/or CSS3 is supported) and serverside (when posted 
to Services/CreateAccount). You can verify a bunch of things at 
compile-time, including that the service exists or that the 
validation contains valid regex. And best of all, it's actually 
readable unlike if you went with a mixin approach. You would end 
up having 7 random mixins in that above form, and have to 
manually check each one to see if it's creating code or just 
creating an attribute. This way, you can see the @ and know it's 
an attribute immediately.

Another thing that doesn't come up yet but may in the future: 
reflection. It seems worrying to have random mixins adding 
reflection info, as that's a job for the compiler. It knows about 
when reflection is enabled, it knows how much it needs to 
generate, if things exist after optimization, etc. There's no 
point leaving that to a mixin and having to keep it in sync with 
the compiler. This way though, there's no need. The reflection 
data would just have an annotations property that can be accessed.


More information about the Digitalmars-d mailing list