View mode: basic / threaded / horizontal-split · Log in · Help
March 16, 2012
Re: Proposal: user defined attributes
On Fri, 16 Mar 2012 09:35:54 -0400, Adam D. Ruppe  
<destructionator@gmail.com> wrote:

> On the ride over here today, I had a thought that
> I think neatly solves the user defined attribute
> question.
>
> enum Serializable { yes, no }
>
> @note(Serializable.yes) int a;

I thought @<symbol> was supposed to be a user-defined annotation.   
Otherwise, why did we introduce @syntax?

I'd rather see something like this:

@annotation serializable(bool x = true) {return x ? Serializable.yes :  
Serializable.no;}  // implicit auto

@serializable int a;
@serializable(false) int b;

Where annotations have to be CTFE-able (because they are constructed at  
compile-time)

-Steve
March 16, 2012
Re: Proposal: user defined attributes
On Friday, 16 March 2012 at 16:57:26 UTC, Steven Schveighoffer 
wrote:
> I thought @<symbol> was supposed to be a user-defined 
> annotation.  Otherwise, why did we introduce @syntax?

idk, to "reduce" the number of keywords or somethiny.

This is why I call it a mistake or missed opportunity
right now though: @property, @safe, @disable, @system,
and @trusted have already made a claim on the @syntax.

Now, we have to work around that, which is why I'm
thinking @note(expression) rather than @<something>.

> I'd rather see something like this:

I could live with that too, but I think it'd be harder
to make happen due to potential clashes with the current
thing @ is used for.
March 16, 2012
Re: Proposal: user defined attributes
On Fri, 16 Mar 2012 13:36:42 -0400, Adam D. Ruppe  
<destructionator@gmail.com> wrote:

> On Friday, 16 March 2012 at 16:57:26 UTC, Steven Schveighoffer wrote:
>> I thought @<symbol> was supposed to be a user-defined annotation.   
>> Otherwise, why did we introduce @syntax?
>
> idk, to "reduce" the number of keywords or somethiny.

Quote from TDPL (section 5.9.1 on page 156):

"Attributes, always introduced with @, are simple adornments specifying  
certain features for the symbol being defined.  Some attributes are  
recognized by the compiler; some are defined and used by the programmer  
alone."

I assumed this was true, and thought so even before TDPL came out.  See  
http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP6

> This is why I call it a mistake or missed opportunity
> right now though: @property, @safe, @disable, @system,
> and @trusted have already made a claim on the @syntax.

I think those are just compiler-defined attributes.  They aren't keywords  
in the sense that the parser doesn't treat them as special.  They are just  
another type of symbol.

> I could live with that too, but I think it'd be harder
> to make happen due to potential clashes with the current
> thing @ is used for.

meh, just don't use @safe, @property, @disable, @system, and @trusted.  I  
don't see a huge number of compiler-defined attributes springing up.  Nor  
do I see a huge number of library or user-defined ones springing up.

-Steve
March 16, 2012
Re: Proposal: user defined attributes
On 3/16/12, Adam D. Ruppe <destructionator@gmail.com> wrote:
> The current language solution isn't really *bad* with enough
> library help, but it isn't particularly *good* either and I
> don't think it can be. I've tried a few things, and I still
> see the lack of user annotations as D's biggest miss right now.

Yeah, but I would say if we had even better compile-time introspection
we could have the freedom to implement any number of annotation
implementations in library code. When you put something into the
language you have to depend on C++ hackers to implement and then
inevitably fix the upcoming bugs in the front-end (ICEs are an
annoying blocker), and there's always that issue where the devs are
against adding new features to an existing language feature. (say
annotations were implemented, soon enough someone is going to complain
it doesn't have enough functionality and that it needs to be
extended).

Personally I'd love it if we had more __traits and compile-time
introspection abilities.
March 16, 2012
Re: Proposal: user defined attributes
On Friday, 16 March 2012 at 18:07:18 UTC, Steven Schveighoffer 
wrote:
> Quote from TDPL (section 5.9.1 on page 156):

Huh. There's nothing I can see in the compiler that even
hints at this. The @ thing is just another storage class
as far as it's concerned right now.

> Nor do I see a huge number of library or user-defined ones 
> springing up.

Yeah.

I still really like my expression idea though, but
thinking about your strategy, we could say:

When you see @, if it is a compiler word after it,
parse it that way. Otherwise, try to get a function
call out of it.

Treat the function call as an enum and add it to the
list. Thus, it is CTFE, namespaced, etc. like normal.

The return value is appended to the declaration's
attribute expression list (so the end result is the same
as I was thinking.)


I'm pretty sure that'd work..
March 16, 2012
Re: Proposal: user defined attributes
On Fri, 16 Mar 2012 14:33:37 -0400, Adam D. Ruppe  
<destructionator@gmail.com> wrote:

> On Friday, 16 March 2012 at 18:07:18 UTC, Steven Schveighoffer wrote:
>> Quote from TDPL (section 5.9.1 on page 156):
>
> Huh. There's nothing I can see in the compiler that even
> hints at this. The @ thing is just another storage class
> as far as it's concerned right now.

Right, the user-defined portion is not implemented.

>
>> Nor do I see a huge number of library or user-defined ones springing up.
>
> Yeah.
>
> I still really like my expression idea though, but
> thinking about your strategy, we could say:
>
> When you see @, if it is a compiler word after it,
> parse it that way. Otherwise, try to get a function
> call out of it.

The way I'd like to see it work (and not being a compiler writer, I have  
no idea if/how this would work) is:

When you see @, call a CTFE function with that name.

The compiler defines intrinsic functions @property, @disable, etc.  which  
return intrinsic data types that get appended to the attribute list.  Then  
the compiler recognizes those data types in the attribute list when  
deciding how things should be compiled.

This might not be feasible given the current implementation, or how  
compilers are designed, I have no idea.

> The return value is appended to the declaration's
> attribute expression list (so the end result is the same
> as I was thinking.)

Yes.  And I'd like to see the other intrinsic attributes appended (and  
queryable) as well.

What we also may need in the @annotation declaration is an alias of the  
thing being compiled (again, don't know how feasible this is)

for example:

@annotation property(alias sym)() { static assert(is(sym == function));  
return INTRINSIC.isProperty;}

Maybe that's going too far :)

-Steve
March 16, 2012
Re: Proposal: user defined attributes
Am Fri, 16 Mar 2012 16:21:41 +0100
schrieb Piotr Szturmaj <bncrbme@jadamspam.pl>:

> > @note(Serializable.yes) int a;
> 
> This is just enum. If you use struct or class attributes (like in C#) 
> then direct @Struct(constructor args..) might be better.
> 
> 
+1

> > The expression inside is appended to a list on
> > the declaration.
> >
> > This would be valid on variables, functions,
> > function parameters, struct members, etc.
> >
> > 2) __traits(getNotes, decl). This returns a tuple
> > of all the note expressions.
> >
> > foreach(i, exp; __traits(getNotes, a)) {
> > static assert(is(typeof(exp) == Serializable);
> > static assert(exp == Serializable.yes);
> > }
> 
> This is nice. Also it's base for library functions like hasNotes or 
> getNotes!(Symbol, MyAttribute).
+1

> > 1) how do you define what is and is not a valid attribute?
> >
> 
> It should be any user-defined type that may be used at compile-time.
> For example @UUID("...") should be available out of the box.

Or we could add a @attribute attribute:

@attribute struct Test
{
   this(int a) {}...
}

@Test(99)
string someTestVal;

> > 2) OK, how do you namespace things so different libraries don't
> > get different results?
> >
> > That's where the beauty of the expression type comes in: D
> > already has namespaces. foo.Serializable != bar.Serializable,
> > so there's no conflict.
> >
> > We simply declare types. The enum X {yes, no} pattern is already
> > common in Phobos, and is also the best way to express a bool
> > condition here. (Technically, @note(true) would compile, but it'd
> > be much less useful than declaring a name for the note too, with an
> > enum.)
> >
> > Name conflicts is a problem already solved by the language.
> 
> Yes, it should be possible to write @std.UUID("").
> 
And all normal import rules should work for user defined attributes as
well (renamed imports, static imports, ...).
March 17, 2012
Re: Proposal: user defined attributes
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.
March 17, 2012
Re: Proposal: user defined attributes
On 3/17/12, Kapps <opantm2+spam@gmail.com> wrote:
> @WebForm("Account");
> @PostTo("Services/CreateAccount")
> @SecureOnly(true)
> struct CreateAccountForm {

That kind of turns D from a structural to a declarative language. :p
March 17, 2012
Re: Proposal: user defined attributes
On Saturday, 17 March 2012 at 00:54:02 UTC, Andrej Mitrovic wrote:
> On 3/17/12, Kapps <opantm2+spam@gmail.com> wrote:
>> @WebForm("Account");
>> @PostTo("Services/CreateAccount")
>> @SecureOnly(true)
>> struct CreateAccountForm {
>
> That kind of turns D from a structural to a declarative 
> language. :p

Web design is quite a declarative thing. :) The code is already 
written for you, why bother writing it again instead of just 
writing it once and passing along essentially parameters to it.

Anywho, something like that is a somewhat extreme case. Basic 
things include @serializable or @notserialized (or 
@serialized(false)). With the topic of dynamic/scripting 
languages, other things can include @scripted to indicate a 
method or class can be accessed from the script, or 
@scripted(Security.low) to indicate user scripts can access it 
and not just game scripts. This prevents having to make annoying 
bindings and communicate what's passed in to the script compiler. 
Instead, you can find out everything that can be passed in at 
compile-time, and upon script compilation you can verify the 
script has access to all of these methods, then statically call 
them without any of the performance hit you would normally have 
by using scripting, yet with the safety.
1 2 3 4 5 6
Top | Discussion index | About this forum | D home