November 26, 2012
On 26 November 2012 18:17, Manu <turkeyman@gmail.com> wrote:

> On 26 November 2012 17:44, Adam D. Ruppe <destructionator@gmail.com>wrote:
>
>> On Monday, 26 November 2012 at 15:39:35 UTC, Manu wrote:
>>
>>> Properties look like variables. How do I distinguish properties from proper variables?
>>>
>>
>> I think this will do it:
>>
>> import std.traits;
>> bool isProperty = (functionAttributes!(S.P) &
>> FunctionAttributes.property) ? true : false
>>
>>
>>
>> The way that works in the implementation is checking the mangled name of the function. I wouldn't try anything else because any other difference between a property and a variable is arguably a bug since they are supposed to be mostly interchangable!
>>
>
> That's weird. Why would I call functionAttributes in something that I can't even identify as a function? That's almost self-defeating... but as long as functionAttributes will tolerate being called with basically any argument, function or otherwise, then I guess this is okay...
>

And fail! functionAttributes breaks when I pass basically anything that's not a function >_<


November 26, 2012
On Monday, 26 November 2012 at 16:32:17 UTC, Manu wrote:
> On 26 November 2012 18:17, Manu <turkeyman@gmail.com> wrote:
>
>> On 26 November 2012 17:44, Adam D. Ruppe <destructionator@gmail.com>wrote:
>>
>>> On Monday, 26 November 2012 at 15:39:35 UTC, Manu wrote:
>>>
>>>> Properties look like variables. How do I distinguish properties from
>>>> proper variables?
>>>>
>>>
>>> I think this will do it:
>>>
>>> import std.traits;
>>> bool isProperty = (functionAttributes!(S.P) &
>>> FunctionAttributes.property) ? true : false
>>>
>>>
>>>
>>> The way that works in the implementation is checking the mangled name of
>>> the function. I wouldn't try anything else because any other difference
>>> between a property and a variable is arguably a bug since they are supposed
>>> to be mostly interchangable!
>>>
>>
>> That's weird. Why would I call functionAttributes in something that I
>> can't even identify as a function? That's almost self-defeating... but as
>> long as functionAttributes will tolerate being called with basically any
>> argument, function or otherwise, then I guess this is okay...
>>
>
> And fail! functionAttributes breaks when I pass basically anything that's
> not a function >_<

You could use check for isCallable before using functionAttributes. I don't know if isCallable is supposed to return true for properties once they are fully defined and implemented, but it currently does.
November 26, 2012
On Monday, 26 November 2012 at 16:32:17 UTC, Manu wrote:
> And fail! functionAttributes breaks when I pass basically anything that's not a function >_<

Blargh.. they do that purposefully to, there's a check if(isCallable!T) on the thingy.


You could use that same check though: if !isCallable!T, it cannot be a property right now, so no need to do the other check.


template isProperty(T) if(isCallable!T) {
   enum bool isProperty = (functionAttributes!T & FuncAttribute.property) ? true : false;
}

template isProperty(T) if(!isCallable!T) {
   enum bool isProperty = false; // it isn't callable, so can't be a property
}
November 26, 2012
On 26 November 2012 18:44, Adam D. Ruppe <destructionator@gmail.com> wrote:

> On Monday, 26 November 2012 at 16:32:17 UTC, Manu wrote:
>
>> And fail! functionAttributes breaks when I pass basically anything that's not a function >_<
>>
>
> Blargh.. they do that purposefully to, there's a check if(isCallable!T) on
> the thingy.
>
>
> You could use that same check though: if !isCallable!T, it cannot be a property right now, so no need to do the other check.
>
>
> template isProperty(T) if(isCallable!T) {
>    enum bool isProperty = (functionAttributes!T & FuncAttribute.property)
> ? true : false;
> }
>
> template isProperty(T) if(!isCallable!T) {
>    enum bool isProperty = false; // it isn't callable, so can't be a
> property
> }
>

Error: variable isProperty cannot be read at compile time

...I think I give up. I can't afford to spend any more time on this.

TL;DR, std.traits is extremely brittle, and rather incomplete. As a programmer with deadlines trying to get work done, it is just not yet acceptable >_<


November 26, 2012
On Monday, 26 November 2012 at 17:03:41 UTC, Manu wrote:
> Error: variable isProperty cannot be read at compile time

that doesn't make any sense :S

> TL;DR, std.traits is extremely brittle, and rather incomplete. As a programmer with deadlines trying to get work done, it
> is just not yet acceptable >_<

I totally get this though... just look at this pile of crap from my web.d, which is used in some really ugly conditions.

I don't even know what it all even does or why it works. It was a few weekends of random guessing:


// these are all filthy hacks

template isEnum(alias T) if(is(T)) {
static if (is(T == enum))
enum bool isEnum = true;
else
enum bool isEnum = false;
}

// WTF, shouldn't is(T == xxx) already do this?
template isEnum(T) if(!is(T)) {
enum bool isEnum = false;
}

template isStruct(alias T) if(is(T)) {
static if (is(T == struct))
enum bool isStruct = true;
else
enum bool isStruct = false;
}

// WTF
template isStruct(T) if(!is(T)) {
enum bool isStruct = false;
}

template Passthrough(T) {
T Passthrough;
}

template PassthroughType(T) {
alias T PassthroughType;
}



Soooo yeah. I'm sure there's a way to get what you want, but I'm equally sure you'll have some pain in the mean time that can take a while to figure through.
November 26, 2012
On 26 November 2012 19:11, Adam D. Ruppe <destructionator@gmail.com> wrote:

> On Monday, 26 November 2012 at 17:03:41 UTC, Manu wrote:
>
>> Error: variable isProperty cannot be read at compile time
>>
>
> that doesn't make any sense :S
>
>
>  TL;DR, std.traits is extremely brittle, and rather incomplete. As a
>> programmer with deadlines trying to get work done, it
>> is just not yet acceptable >_<
>>
>
> I totally get this though... just look at this pile of crap from my web.d, which is used in some really ugly conditions.
>
> I don't even know what it all even does or why it works. It was a few weekends of random guessing:
>
>
> // these are all filthy hacks
>
> template isEnum(alias T) if(is(T)) {
> static if (is(T == enum))
> enum bool isEnum = true;
> else
> enum bool isEnum = false;
> }
>
> // WTF, shouldn't is(T == xxx) already do this?
> template isEnum(T) if(!is(T)) {
> enum bool isEnum = false;
> }
>
> template isStruct(alias T) if(is(T)) {
> static if (is(T == struct))
> enum bool isStruct = true;
> else
> enum bool isStruct = false;
> }
>
> // WTF
> template isStruct(T) if(!is(T)) {
> enum bool isStruct = false;
> }
>
> template Passthrough(T) {
> T Passthrough;
> }
>
> template PassthroughType(T) {
> alias T PassthroughType;
> }
>
>
>
> Soooo yeah. I'm sure there's a way to get what you want, but I'm equally sure you'll have some pain in the mean time that can take a while to figure through.
>

Perhaps, but I've already spent days on this, and many hours of overtime!!
I need to draw the line.
Here's what I have, and it's not even close to working:

template isType( alias T )
{
enum isType = is( T );
}
template isType( T )
{
enum isType = is( T );
}

template isFunction( alias T )
{
enum isFunction = is( typeof( T ) == function );
}
template isFunction( T )
{
enum isFunction = is( T == function );
}

template isEnum( alias T )
{
template knownAtCompileTime( alias T )
{
// enum knownAtCompileTime = is( typeof( { enum e = T; } ) ); // immutable
breaks this approach
enum knownAtCompileTime = !__traits(compiles, ( ref typeof( T ) _x_ ) {}( T
) ); // hack to see if we can pass it by ref
}

enum isEnum = is( typeof( T ) == enum ) || knownAtCompileTime!T;
}
template isEnum( T )
{
enum isEnum = is( T == enum );
}

template isProperty( alias T ) if(isCallable!T)
{
bool isProperty = (functionAttributes!T & FunctionAttribute.property) ?
true : false;
}
template isProperty( alias T ) if(!isCallable!T)
{
bool isProperty = false;
}
template isProperty( T )
{
bool isProperty = false;
}

template isVariable( alias T )
{
enum isVariable = !is( T ) && is( typeof( T ) ) // if it is not a type, and
does have a type, it starts to look like a variable
&& !isFunction!T // reject function definitions, they can't be assigned to
&& !is( typeof( T ) == void ) // reject modules, which appear as a variable
of type 'void'
&& !isEnum!T // reject enum's
&& !isProperty!T; // seriously, why is this not caught by the function test
above?!
}
template isVariable( T )
{
enum isVariable = false; // types aren't variables
}




import std.stdio;
struct a { void m(); static void n(); }
alias int b;
interface c { void l(); };
int d;
immutable e = 10;
void function() f;
void delegate() g;
void h() {}
enum i = 10;
enum j { k = 10 }
@property int p() { return 10; }

pragma(msg, "isType");
pragma(msg, isType!int);
pragma(msg, isType!a);
pragma(msg, isType!b);
pragma(msg, isType!c);
pragma(msg, isType!d);
pragma(msg, isType!e);
pragma(msg, isType!f);
pragma(msg, isType!g);
pragma(msg, isType!h);
pragma(msg, isType!i);
pragma(msg, isType!j);
pragma(msg, isType!(j.k));
pragma(msg, isType!(c.l));
pragma(msg, isType!(a.m));
pragma(msg, isType!(a.n));
pragma(msg, isType!p);
pragma(msg, isType!std);

pragma(msg, "isFunction");
pragma(msg, isFunction!int);
pragma(msg, isFunction!a);
pragma(msg, isFunction!b);
pragma(msg, isFunction!c);
pragma(msg, isFunction!d);
pragma(msg, isFunction!e);
pragma(msg, isFunction!f);
pragma(msg, isFunction!g);
pragma(msg, isFunction!h);
pragma(msg, isFunction!i);
pragma(msg, isFunction!j);
pragma(msg, isFunction!(j.k));
pragma(msg, isFunction!(c.l));
pragma(msg, isFunction!(a.m));
pragma(msg, isFunction!(a.n));
pragma(msg, isFunction!p);
pragma(msg, isFunction!std);

pragma(msg, "isEnum");
pragma(msg, isEnum!int);
pragma(msg, isEnum!a);
pragma(msg, isEnum!b);
pragma(msg, isEnum!c);
pragma(msg, isEnum!d);
pragma(msg, isEnum!e);
pragma(msg, isEnum!f);
pragma(msg, isEnum!g);
pragma(msg, isEnum!h);
pragma(msg, isEnum!i);
pragma(msg, isEnum!j);
pragma(msg, isEnum!(j.k));
pragma(msg, isEnum!(c.l));
pragma(msg, isEnum!(a.m));
pragma(msg, isEnum!(a.n));
pragma(msg, isEnum!p);
pragma(msg, isEnum!std);

pragma(msg, "isProperty");
pragma(msg, isProperty!int);
pragma(msg, isProperty!a);
pragma(msg, isProperty!b);
pragma(msg, isProperty!c);
pragma(msg, isProperty!d);
pragma(msg, isProperty!e);
pragma(msg, isProperty!f);
pragma(msg, isProperty!g);
pragma(msg, isProperty!h);
pragma(msg, isProperty!i);
pragma(msg, isProperty!j);
pragma(msg, isProperty!(j.k));
pragma(msg, isProperty!(c.l));
pragma(msg, isProperty!(a.m));
pragma(msg, isProperty!(a.n));
pragma(msg, isProperty!p);
pragma(msg, isProperty!std);

pragma(msg, "isVariable");
pragma(msg, isVariable!int);
pragma(msg, isVariable!a);
pragma(msg, isVariable!b);
pragma(msg, isVariable!c);
pragma(msg, isVariable!d);
pragma(msg, isVariable!e);
pragma(msg, isVariable!f);
pragma(msg, isVariable!g);
pragma(msg, isVariable!h);
pragma(msg, isVariable!i);
pragma(msg, isVariable!j);
pragma(msg, isVariable!(j.k));
pragma(msg, isVariable!(c.l));
pragma(msg, isVariable!(a.m));
pragma(msg, isVariable!(a.n));
pragma(msg, isVariable!p);
pragma(msg, isVariable!std);


November 26, 2012
On Monday, 26 November 2012 at 17:30:46 UTC, Manu wrote:
> Error: variable isProperty cannot be read at compile time

This is easy now that I see the code:
> template isProperty( T )
> {
> bool isProperty = false;
> }


That should be enum bool isProperty = false. The enum is important because that makes it a compile time value, instead of a runtime variable like regular "bool isProperty".

Generally if you want something at compile time, enum is the magic keyword to put before an otherwise normal variable declaration.

Fix that in both places you did it... and import std.traits of course, and your code compiles.

Not sure if it is right, but it compiles and spits a bunch of output.

November 26, 2012
On 26 November 2012 19:38, Adam D. Ruppe <destructionator@gmail.com> wrote:

> On Monday, 26 November 2012 at 17:30:46 UTC, Manu wrote:
>
>> Error: variable isProperty cannot be read at compile time
>>
>
> This is easy now that I see the code:
>
>  template isProperty( T )
>> {
>> bool isProperty = false;
>> }
>>
>
>
> That should be enum bool isProperty = false. The enum is important because that makes it a compile time value, instead of a runtime variable like regular "bool isProperty".
>
> Generally if you want something at compile time, enum is the magic keyword to put before an otherwise normal variable declaration.
>
> Fix that in both places you did it... and import std.traits of course, and your code compiles.
>
> Not sure if it is right, but it compiles and spits a bunch of output.
>

Ah crap! Yes I know, this is effectively a typo, I've just been staring at
this way too long ;)
It still doesn't work though. Some of that output is wrong, and when I
actually use these in context, there are further problems. But it's getting
there.


November 26, 2012
On 26 November 2012 19:38, Adam D. Ruppe <destructionator@gmail.com> wrote:

> On Monday, 26 November 2012 at 17:30:46 UTC, Manu wrote:
>
>> Error: variable isProperty cannot be read at compile time
>>
>
> This is easy now that I see the code:
>
>  template isProperty( T )
>> {
>> bool isProperty = false;
>> }
>>
>
>
> That should be enum bool isProperty = false. The enum is important because that makes it a compile time value, instead of a runtime variable like regular "bool isProperty".
>
> Generally if you want something at compile time, enum is the magic keyword to put before an otherwise normal variable declaration.
>
> Fix that in both places you did it... and import std.traits of course, and your code compiles.
>
> Not sure if it is right, but it compiles and spits a bunch of output.
>

Actually, look back in the thread, I blindly copied that from you! ;) .. Yes, if obviously should have been enum.


November 26, 2012
On Monday, 26 November 2012 at 18:05:11 UTC, Manu wrote:
> Actually, look back in the thread, I blindly copied that from you! ;) ..

gah, that's what I get for rushing through it!