August 21, 2013 Re: Typeof woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marek Janukowicz | Yes, "is" expression suppresses errors and simply returns "false" (as error is not valid type). It is used in a common D idiom - "is(typeof(<expression>))" to check if certain expression is valid and compiles in current scope. |
August 21, 2013 Re: Typeof woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marek Janukowicz | On Wed, Aug 21, 2013 at 08:32:09AM +0200, Marek Janukowicz wrote: > H. S. Teoh wrote: [...] > > To get around this, you will need to use static if, maybe something like this: > > > > void list() { > > // Warning: untested code > > foreach(s; __traits(derivedMembers, typeof(this))) { > > static if (is(typeof(__traits(getMember, this, s)) type)) { > > // here, 'type' is bound to the type of > > // the member. > > } > > } > > } > > > > This uses the is(X Y) form, where if X is a valid type, then it gets aliased to Y inside the static if block. (I have to admit I'm not that pleased with D's is-expressions due to their confusing syntax, but they do work and are quite a powerful tool to use once you understand them.) > > This code works, thank you. However, if I may share my newbie impression - current traits implementation looks not complete to me. What I want to do is to process those members that are of certain type - instead of a nice one- liner to identify those, I already need two and the first (the one you provided above) looks like a hack to me, because I have to check if some expression is valid. The whole issue (which to me looks like a quite standard metaprogramming task) already took me a few hours (and also some time of you and the other helpful guys) and I can't get rid of the impression either the docs are lacking or we could use some more traits. >From what I can tell, the traits are designed to be minimal, just enough to cover what needs to be done, so sometimes they may not have the nicest or most concise interfaces. You can always add some syntactic sugar to it using templates, of course. That, and the docs probably could use a facelift. :) This isn't the first time somebody's found the docs too obscure or unhelpful. In any case, you're not the first one who found the __traits syntax cumbersome. I know I did when I first started using it. It's probably too late to change __traits syntax, but I can see adding some nice wrapper templates to std.traits to make these things less annoying. Some stuff is already there, but a few more would make introspection easier. > >> What's even more interesting it's just alias problem, the > >> expression "typeof(__traits(getMember, this, s))" might be used eg. > >> in static if even for enums. > >> > >> Is this a bug or do I miss something (again)? > > [...] > > > > Are you sure about that? That doesn't sound right to me. > > Yes, I'm sure, here goes modified code: > import std.stdio; > > class A { > > int a; > enum Smth { A }; > > void list () { > foreach( s; __traits(derivedMembers, typeof(this))) { > //alias type = typeof(__traits(getMember, this, s)); > static if (is (typeof(__traits(getMember, this, s)) == int)) { > writefln ("%s is int", s ); [...] Ah, you're putting it inside an is(...) expression, that's why it "works". :) The whole point of is(...) is to check if a particular expression makes sense (aka "has a type", the idea being that if the expression is invalid, like if you try to perform arithmetic on types or if use a type as a value). So naturally, it suppresses type-related errors inside and just returns false instead. This is one of the dark corners in D where things are more obscure than they need to be. The whole syntax/semantics of is(...), while quite complete and functional, leaves a lot to be desired in terms of readability / usability. A lot of newcomers have trouble with it, including myself when I first encountered it. In any case, if you're just looking for members of a particular known type, then using is(typeof(__traits(getMember, ...)...)) should be good enough. T -- Political correctness: socially-sanctioned hypocrisy. |
August 22, 2013 Re: Typeof woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On 08/21/13 02:15, Dicebot wrote:
> typeof only accepts expressions, not types.
>
> Workaround:
>
> template myTypeOf(T...)
> if (T.length == 1)
> {
> static if (is(T))
> alias myTypeOf = T;
> else
> alias myTypeOf = typeof(T);
> }
Keep in mind that 'typeof' is special - it won't evaluate the argument. Which could be any expression (not just the subset allowed as template parms).
artur
|
August 22, 2013 Re: Typeof woes | ||||
---|---|---|---|---|
| ||||
On 08/21/13 02:43, H. S. Teoh wrote:
> On Wed, Aug 21, 2013 at 02:24:18AM +0200, Andrej Mitrovic wrote:
>> On 8/21/13, H. S. Teoh <hsteoh@quickfur.ath.cx> wrote:
>>> and typeof(this.Smth) is invalid because this.Smth is already a type, so you can't apply typeof to it.
>>
>> I am beginning to wonder if typeof(typeof(expr)) is worthy of an
>> error. Would we end up having any bugs if we were to allow typeof() to
>> work on types (IOW it would just alias itself to the type)?
>>
>> I guess the only way to find out is to try it out in a compiler branch, but I'm genuinely curious.
>
> Hmm.
>
> If typeof were idempotent on types, then it would provide nice closure properties (as in mathematical closure, not delegates) if we ever implement the proposed typetuple/std.typecons.Tuple unification from the other thread:
>
> typeof(tup(1,"a")) == tup(int,string)
> typeof(tup(int,"a")) == tup(int,string)
> typeof(tup(int,string)) == tup(int,string)
>
> This alleviates one of the nagging problems with mixed tuples that
> contain both types and expressions. Then the only left to do is to
> specify that a tuple can be used as a type only if it contains only
> types (IOW, if is(typeof(tup)==tup), a rather nice way to express it),
> and a tuple can be used as a value (assigned to variables, etc.) only if
> it contains only values.
>
> "Mixed" tuples can still be used as template arguments, and you can always apply typeof to them.
You do realize that this is the way the built-in tuples work already? With the exception of that last case, which of course is an error right now. (I'm not sure that allowing typeof(Type) would be a good idea)
artur
|
Copyright © 1999-2021 by the D Language Foundation