Re: Dealing with raw types as attributes
On Thursday, 1 November 2018 at 16:14:45 UTC, Neia Neutuladh wrote: The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: struct Foo { string name = "unknown"; } @Foo int bar; IIRC symbol reference is a primary expression.
Re: Dealing with raw types as attributes
On Friday, 2 November 2018 at 04:18:47 UTC, Neia Neutuladh wrote: On Fri, 02 Nov 2018 04:01:00 +, Nicholas Wilson wrote: By noting that all (interesting for the purpose of UDA's i.e. not void) types have a .init or you could do static if (is(typeof(uda) == Foo) || is(uda == Foo)) Which, again, only tests for presence, when I want to check for presence *and* get the value, which should be Foo.init if the person supplied the raw type. template GetMeTheValue(value...) if(value.length == 1) { static if (is(typeof(value[0].init == value[0]) // A type enum GetMeTheValue = value[0].init; else enum GetMeTheValue = value[0]; } ... static if (is(typeof(GetMeTheValue!uda) == Foo)
Re: Dealing with raw types as attributes
On Fri, 02 Nov 2018 04:01:00 +, Nicholas Wilson wrote: > By noting that all (interesting for the purpose of UDA's i.e. not void) > types have a .init > > or you could do > > static if (is(typeof(uda) == Foo) || is(uda == Foo)) Which, again, only tests for presence, when I want to check for presence *and* get the value, which should be Foo.init if the person supplied the raw type.
Re: Dealing with raw types as attributes
On Friday, 2 November 2018 at 03:13:19 UTC, Neia Neutuladh wrote: On Fri, 02 Nov 2018 00:36:18 +, Nicholas Wilson wrote: What do you do to handle this? @Foo() int bar; instead of @Foo int bar; Right. And if you're offering a library with UDAs for other people to use? I mean I suppose if you really wanted to avoid the parentheses, you could do static foreach (uda; __traits(getAttributes, bar)) { static if (is(typeof(uda.init) == Foo) { pragma(msg, "bar is @Foo"); } } By noting that all (interesting for the purpose of UDA's i.e. not void) types have a .init or you could do static if (is(typeof(uda) == Foo) || is(uda == Foo))
Re: Dealing with raw types as attributes
On Fri, 02 Nov 2018 00:36:18 +, Nicholas Wilson wrote: >> What do you do to handle this? > > @Foo() int bar; > > instead of > > @Foo int bar; Right. And if you're offering a library with UDAs for other people to use?
Re: Dealing with raw types as attributes
On Thursday, 1 November 2018 at 16:14:45 UTC, Neia Neutuladh wrote: The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: Indeed UDA are odd beasts: https://issues.dlang.org/show_bug.cgi?id=19127 What do you do to handle this? @Foo() int bar; instead of @Foo int bar; https://run.dlang.io/is/3USj6h
Re: Dealing with raw types as attributes
On Thursday, 1 November 2018 at 20:33:10 UTC, Neia Neutuladh wrote: On Thu, 01 Nov 2018 20:01:51 +, Stanislav Blinov wrote: Check if an UDA is a type?.. As in, not just `is(uda == Foo)`, but simply `is(uda)`: Which works, but generally makes things more complex in code that's already pretty deeply nested. It's also something I have to worry about every time I do the static foreach to get UDAs, in the cases where that's more than once. Yes, it does :( I could use a customized version of [getUDAs] that replaces @Type with @Type.init, and that's a reasonable choice... That can't be generic, as you can have UDAs that don't have an .init: enum XXX; @XXX int bar; static foreach (uda; __traits(getAttributes, bar)) { static if (is(uda == XXX)) { pragma(msg, "bar is XXX"); } } ...but so long as you can live without such UDAs, I guess it could work.
Re: Dealing with raw types as attributes
On Thu, 01 Nov 2018 20:01:51 +, Stanislav Blinov wrote: > Check if an UDA is a type?.. As in, not just `is(uda == Foo)`, > but simply `is(uda)`: Which works, but generally makes things more complex in code that's already pretty deeply nested. It's also something I have to worry about every time I do the static foreach to get UDAs, in the cases where that's more than once.
Re: Dealing with raw types as attributes
On Thu, 01 Nov 2018 11:35:27 -0700, Ali Çehreli wrote: > On 11/01/2018 09:14 AM, Neia Neutuladh wrote: >> The spec says that a user-defined attribute must be an expression, but >> DMD accepts a wide range of things as UDAs: >> >>struct Foo { string name = "unknown"; } >>@Foo int bar; >> >> `bar` has the *type* Foo as an attribute. It's not an *instance* of >> Foo. So if I try to look at the UDAs: > > That would work with hasUDA(). I have an example here: > >http://ddili.org/ders/d.en/uda.html That lets me test for presence, nothing more. While that's useful, I usually have a UDA struct whose fields I need to access. std.traits.getUDAs doesn't hide the difference between @Foo and @Foo(), so that's also not an option. I could use a customized version of that that replaces @Type with @Type.init, and that's a reasonable choice when I know other people aren't going to deal with that annotation type.
Re: Dealing with raw types as attributes
On Thursday, 1 November 2018 at 16:14:45 UTC, Neia Neutuladh wrote: The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: struct Foo { string name = "unknown"; } @Foo int bar; `bar` has the *type* Foo as an attribute. It's not an *instance* of Foo. So if I try to look at the UDAs: static foreach (uda; __traits(getAttributes, bar)) { static if (is(typeof(uda) == Foo)) { pragma(msg, "bar is @Foo"); } } That just doesn't work; typeof(Foo) isn't anything, so is(typeof(Foo) == Foo) is false. I can change my code to read `static if (is(uda == Foo))`. But that obviously fails: @Foo("customName") int bar2; What do you do to handle this? Check if an UDA is a type?.. As in, not just `is(uda == Foo)`, but simply `is(uda)`: ``` struct Foo { string name = "unknown"; } @Foo @string @Foo("hello") int bar; static foreach (uda; __traits(getAttributes, bar)) { static if (is(uda)) { // if `uda` is a type... static if (is(uda == Foo)) { pragma(msg, "bar is @Foo!!!"); } else { pragma(msg, "bar is "~uda.stringof); } } else { // if `uda` is not a type... pragma(msg, "bar is "~uda.stringof); } } ```
Re: Dealing with raw types as attributes
On 11/01/2018 09:14 AM, Neia Neutuladh wrote: The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: struct Foo { string name = "unknown"; } @Foo int bar; `bar` has the *type* Foo as an attribute. It's not an *instance* of Foo. So if I try to look at the UDAs: That would work with hasUDA(). I have an example here: http://ddili.org/ders/d.en/uda.html Ali
Dealing with raw types as attributes
The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: struct Foo { string name = "unknown"; } @Foo int bar; `bar` has the *type* Foo as an attribute. It's not an *instance* of Foo. So if I try to look at the UDAs: static foreach (uda; __traits(getAttributes, bar)) { static if (is(typeof(uda) == Foo)) { pragma(msg, "bar is @Foo"); } } That just doesn't work; typeof(Foo) isn't anything, so is(typeof(Foo) == Foo) is false. I can change my code to read `static if (is(uda == Foo))`. But that obviously fails: @Foo("customName") int bar2; What do you do to handle this? My current workaround is to make the attribute into a struct instance and use opCall in lieu of constructors: struct _Foo { string name; _Foo opCall(string name) { _Foo f; f.name = name; return f; } } enum _Foo Foo = _Foo.init; Now I can use `static if (is(typeof(uda) == _Foo))` and it always works. But are there better options? Any obvious flaws?