Re: Dealing with raw types as attributes

2018-11-02 Thread Kagamin via Digitalmars-d-learn
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

2018-11-01 Thread Nicholas Wilson via Digitalmars-d-learn

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

2018-11-01 Thread Neia Neutuladh via Digitalmars-d-learn
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

2018-11-01 Thread Nicholas Wilson via Digitalmars-d-learn

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

2018-11-01 Thread Neia Neutuladh via Digitalmars-d-learn
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

2018-11-01 Thread Nicholas Wilson via Digitalmars-d-learn
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

2018-11-01 Thread Stanislav Blinov via Digitalmars-d-learn
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

2018-11-01 Thread Neia Neutuladh via Digitalmars-d-learn
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

2018-11-01 Thread Neia Neutuladh via Digitalmars-d-learn
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

2018-11-01 Thread Stanislav Blinov via Digitalmars-d-learn
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

2018-11-01 Thread Ali Çehreli via Digitalmars-d-learn

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

2018-11-01 Thread Neia Neutuladh via Digitalmars-d-learn
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?