www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - __traits() to get parameter details only ? ... hasMember looks up

reply someone <someone somewhere.com> writes:
I have the following chunk of code that needs to conditionally 
instantiate existing classes (at compilation time) named 
classTickerCustom{ExchangeID} with one or ... two parameters (if 
any); eg:

```d
/// securities trading on exchange primary currency; eg: USD

... = new classTickerCustomNYSE("AMC");
... = new classTickerCustomNASDAQ("TSLA");

/// securities trading on exchange secondary currency; eg: EUR

... = new classTickerCustomNYSE("XXX", "EUR");
... = new classTickerCustomNASDAQ("YYY", "EUR");

/// not real cases ... of course
```

And I already have a working solution using:

```d
static if (__traits(hasMember, "...", "...") == true) {

    ...

}
```

More specifically:

```d
...

mixin(format!

    ` /// code chunk

    static if (__traits(hasMember, r"classTickerCustom%1$s"d, 
r"lstrCurrencyID"d) == true) { /// checking whether target class 
has an optional second parameter labeled lstrCurrencyID:

       classTickerCustom%1$s lobjTickerCustom%1$s = new 
classTickerCustom%1$s(
          ludtTicker.symbolID,
          ludtTicker.currencyID /// overriding exchange primary 
currency ID with given one
          );

    } else {

       classTickerCustom%1$s lobjTickerCustom%1$s = new 
classTickerCustom%1$s(ludtTicker.symbolID);

    }

    `(sudtExchange.ID) /// code chunk

); /// mixin ending

...
```

However, __traits(hasMember, ...) checks for the existence of 
anything labeled lstrCurrencyID within the class (eg: unrelated 
variables with same name; not gonna happen, but, I like to code 
it the right way); so, question is: is there any way to search 
the parameter declarations only ?

Something akin to 
https://dlang.org/spec/traits.html#getParameterStorageClasses but 
for the parameter types/labels
Aug 04 2021
next sibling parent reply Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Wednesday, 4 August 2021 at 15:08:24 UTC, someone wrote:

 However, __traits(hasMember, ...) checks for the existence of 
 anything labeled lstrCurrencyID within the class (eg: unrelated 
 variables with same name; not gonna happen, but, I like to code 
 it the right way); so, question is: is there any way to search 
 the parameter declarations only ?

 Something akin to 
 https://dlang.org/spec/traits.html#getParameterStorageClasses 
 but for the parameter types/labels
What do you mean by parameter type? Are you referring to property functions or just whether there is a field in there? In both cases you need to get that symbol with __traits(getMember ...). If it is about property then check whether the symbol is a function and if so fetch the function attributes with functionAttributes template and check if it is marked as a property. If this is about field of the class then you can test with FieldNameTuple. Since you're using classes consider just declaring an interface that denotes that implementor has this field, it would be much easier to check for it, and easier for compiler since it avoids compile time magic. Best regards, Alexandru.
Aug 04 2021
next sibling parent someone <someone somewhere.com> writes:
On Wednesday, 4 August 2021 at 16:41:04 UTC, Alexandru Ermicioi 
wrote:
 On Wednesday, 4 August 2021 at 15:08:24 UTC, someone wrote:

 However, __traits(hasMember, ...) checks for the existence of 
 anything labeled lstrCurrencyID within the class (eg: 
 unrelated variables with same name; not gonna happen, but, I 
 like to code it the right way); so, question is: is there any 
 way to search the parameter declarations only ?

 Something akin to 
 https://dlang.org/spec/traits.html#getParameterStorageClasses 
 but for the parameter types/labels
What do you mean by parameter type? Are you referring to property functions or just whether there is a field in there?
Labels, identifiers I meant, I suppose I heavily redacted and types stuck, sorry for the confusion.
 In both cases you need to get that symbol with 
 __traits(getMember ...).
 If it is about  property then check whether the symbol is a 
 function and if so fetch the function attributes with  
 functionAttributes template and check if it is marked as a 
 property.
Nope. Nothing about property. Furthermore, as a side-note: I removed all property usage from my code and I am not using them anymore since this language feature seems to be half-baked from what I am seeing here in the forums.
 If this is about field of the class then you can test with 
 FieldNameTuple.

 Since you're using classes consider just declaring an interface 
 that denotes that implementor has this field, it would be much 
 easier to check for it, and easier for compiler since it avoids 
 compile time magic.

 Best regards,
 Alexandru.
Aug 04 2021
prev sibling parent reply someone <someone somewhere.com> writes:
On Wednesday, 4 August 2021 at 16:41:04 UTC, Alexandru Ermicioi 
wrote:

 Since you're using classes consider just declaring an interface 
 that denotes that implementor has this field, it would be much 
 easier to check for it, and easier for compiler since it avoids 
 compile time magic.
I am not sure I am following you regarding this one: you mean coding an interface for the sole-purpose to use traits more easily ? I mean, use it to unambiguously discern whether the required member exists since an interface won't have variables nor anything implementation-related which could confuse the check ? Like coding: ```d private interface interfaceTickerCustom1 { ... } /// one-parameter granted private interface interfaceTickerCustom2 { ... } /// two-parameters granted public class classTickerCustomNYSE : interfaceTickerCustom1 { this( const dstring lstrSymbolID ) { } } public class classTickerCustomNASDAQ : interfaceTickerCustom2 { this( const dstring lstrSymbolID, const dstring lstrCurrencyID ) { } } ``` And then checking for classTickerCustom{EchangeID} with traits for the existence of the interface the class is being tied to ? Is that what you mean ?
Aug 04 2021
parent reply Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Wednesday, 4 August 2021 at 22:28:53 UTC, someone wrote:
 Is that what you mean ?
Not really. I was assuming you were talking about property methods, and if so you could declare such cases: ``` interface HasMutableLstrSymbolId { property lstrSymbolId(); property lstrSymbolId(string id); } interface HasMutableLstrCurrencyId { property lstrCurrencyId(); property lstrCurrencyId(string id); } class NyseTicker : HasMutableLstrSymbolId { //... } class NasdaqTicker : HasMutableLstrSymbolId, HasMutableLstrSymbolId { // ... } ``` Having this structure you would just need to check whether it implements right interface and then once you know it, just set the value. Note, that this approach won't work nicely if you have lots of fields to set. In this case I'd try a builder pattern, where you have a common builder interface which has Nasdaq and Nyse implementation that builds respective classes out of information available. Now from the other replies it seems you want to get constructor arguments. Constructor itself is named __ctor internally (you'll see it listed as such when fetching allMembers), therefore fetch the constructor overload set (you need this because D allows method overloading, and therefore all methods in overload set should be checked), and then iterate over it and check what you're interested in. You can then use std.traits.Parameters to fetch a tuple of param types, or std.traits.ParameterIdentifierTuple for fetching parameter names. As other people recommended you can check std.traits implementation to get insight on the compiler magic they rely to do this. Regarding property methods, even if they are half baked, they are still useful in denoting properties that can be fetched or assigned to a class. It is similar to setters & getters I'm aware. Having properties marked with property also allows template code to be aware which methods are actually representing a property on the object. Also, it is not really necessary to prefix the name of each class or interface with 'class' or 'interface', since this information is already baked into the type itself, and in most of the time may be just unnecessary noise for reading the code.
Aug 04 2021
parent reply someone <someone somewhere.com> writes:
On Thursday, 5 August 2021 at 01:47:36 UTC, Alexandru Ermicioi 
wrote:
 On Wednesday, 4 August 2021 at 22:28:53 UTC, someone wrote:
 Is that what you mean ?
Not really. I was assuming you were talking about property methods, and if so you could declare such cases: ``` interface HasMutableLstrSymbolId { property lstrSymbolId(); property lstrSymbolId(string id); } interface HasMutableLstrCurrencyId { property lstrCurrencyId(); property lstrCurrencyId(string id); } class NyseTicker : HasMutableLstrSymbolId { //... } class NasdaqTicker : HasMutableLstrSymbolId, HasMutableLstrSymbolId { // ... } ``` Having this structure you would just need to check whether it implements right interface and then once you know it, just set the value. Note, that this approach won't work nicely if you have lots of fields to set. In this case I'd try a builder pattern, where you have a common builder interface which has Nasdaq and Nyse implementation that builds respective classes out of information available.
I'll find this very useful for other things I have in mind ... thanks for this one :)
 Now from the other replies it seems you want to get constructor 
 arguments.
 Constructor itself is named __ctor internally
ah ... bingo ! I oftenly see this thing __ctor in the forums but never knew what the hell it was. This is what I need.
 (you'll see it listed as such when fetching allMembers), 
 therefore fetch the constructor overload set (you need this 
 because D allows method overloading, and therefore all methods 
 in overload set should be checked), and then iterate over it 
 and check what you're interested in. You can then use 
 std.traits.Parameters to fetch a tuple of param types, or 
 std.traits.ParameterIdentifierTuple for fetching parameter 
 names. As other people recommended you can check std.traits 
 implementation to get insight on the compiler magic they rely 
 to do this.

 Regarding  property methods, even if they are half baked, they 
 are still useful in denoting properties that can be fetched or 
 assigned to a class. It is similar to setters & getters 

 as I'm aware. Having properties marked with  property also 
 allows template code to be aware which methods are actually 
 representing a property on the object.
Yes, of course I am fully aware of what getters/setters are and thus I started using property because I think it had some "special" functionality/whatever but after a month or so using them and seeing some comments here in the forums I assumed they were half-baked or even going away soon so I threw out them all. IIRC I think somewhere I read Ali saying there's nothing wrong implementing properties the old-way via functions because property has nothing special about it but I can't state where I read what I am stating so take it with a grain of salt.
 Also, it is not really necessary to prefix the name of each 
 class or interface with 'class' or 'interface', since this 
 information is already baked into the type itself, and in most 
 of the time may be just unnecessary noise for reading the code.
Yes yes I know old habits die hard :) I do name like this because I often have interfaceXXX alongside classXXX : interfaceXXX and this helps me keep track of what I am doing. I like to name as related-as-possible. I even still use the prefixed variable naming scheme that almost no new programmer use but this (at least for me) catches lots of errors on the fly -I rarely have a compiler error for a type-mismatch. In the end is what works for each-one. Anyway I am changing the way I usually write code; I already switched behavior/style in many areas: - private: public: sections instead of individually prefixing everything - discarded once-and-for-all excessive cast() usage - discarded in parameters and went back to const Unneeded things I still do due to habit: - explicitly initializing strings; eg: string lstrWhatever = null; - explicitly initializing integers to 0 - explicitly checking bool's; eg: if (lbolWhatever == true) {} Long-story-short: the more you learn the more you adapt to :)
Aug 04 2021
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/4/21 7:21 PM, someone wrote:

 somewhere I read
 Ali saying there's nothing wrong implementing properties the old-way v=
ia
 functions because  property has nothing special about it but I can't
 state where I read what I am stating so take it with a grain of salt.
As I understand it, property is discouraged by the community. That's=20 what I say here: http://ddili.org/ders/d.en/property.html#ix_property. property Quoting the whole section: <quote> property Property functions may be defined with the property attribute as well.=20 However, as a best practice, the use of this attribute is discouraged. import std.stdio; struct Foo { property int a() const { return 42; } int b() const { // =E2=86=90 Defined without property return 42; } } void main() { auto f =3D Foo(); writeln(typeof(f.a).stringof); writeln(typeof(f.b).stringof); } The only effect of the property attribute is when determining the type=20 of an expression that could syntactically be a property function call.=20 As seen in the output below, the types of the expressions f.a and f.b=20 are different: int =E2=86=90 The type of the expression f.a (the return type)= const int() =E2=86=90 The type of the member function Foo.b </quote> Ali P.S. I found that section by searching for "property" on the Index page: http://ddili.org/ders/d.en/ix.html The Index page is linked from the title page (aka index.html) as "The=20 Index Section". (Too many indexes! :) ) http://ddili.org/ders/d.en/index.html
Aug 05 2021
parent someone <someone somewhere.com> writes:
On Thursday, 5 August 2021 at 15:23:24 UTC, Ali Çehreli wrote:

 As I understand it,  property is discouraged by the community. 
 That's what I say here:

   http://ddili.org/ders/d.en/property.html#ix_property. property
I knew I have read it somewhere ... thanks for the clarification Ali !
Aug 05 2021
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 8/4/21 11:08 AM, someone wrote:

 However, __traits(hasMember, ...) checks for the existence of anything 
 labeled lstrCurrencyID within the class (eg: unrelated variables with 
 same name; not gonna happen, but, I like to code it the right way); so, 
 question is: is there any way to search the parameter declarations only ?
Have you looked at [std.traits](https://dlang.org/phobos/std_traits.html) at all? It does a lot of stuff, including giving you parameter names and types. -Steve
Aug 04 2021
parent reply someone <someone somewhere.com> writes:
On Wednesday, 4 August 2021 at 20:13:53 UTC, Steven Schveighoffer 
wrote:
 On 8/4/21 11:08 AM, someone wrote:

 Have you looked at 
 [std.traits](https://dlang.org/phobos/std_traits.html) at all? 
 It does a lot of stuff, including giving you parameter names 
 and types.
No. I didn't know it ever existed :( You mean something like: ```d import std.traits : ParameterIdentifierTuple; static if ([ParameterIdentifierTuple!classTickerCustom%1$s] == ["lstrSymbolID", "lstrCurrencyID"]) { ... } ```
Aug 04 2021
parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Wednesday, 4 August 2021 at 22:01:21 UTC, someone wrote:
 No. I didn't know it ever existed :(
It is good to look at the source code implementations of some of those things too. Most are built out of language features and some of it is simpler to use directly (and some of it are pretty tricky that's educational to look at too).
Aug 04 2021
parent someone <someone somewhere.com> writes:
On Wednesday, 4 August 2021 at 22:22:29 UTC, Adam D Ruppe wrote:
 On Wednesday, 4 August 2021 at 22:01:21 UTC, someone wrote:
 No. I didn't know it ever existed :(
It is good to look at the source code implementations of some of those things too. Most are built out of language features and some of it is simpler to use directly (and some of it are pretty tricky that's educational to look at too).
I totally agree with you on this one; but, you can't expect me (nor anyone else) to gather a mountain of info on just a two-month learning curve coding with D. I learned a LOT, and a lot is not enough, time will do its thing, but more importantly, sometimes I am rethinking the way I usually write code because D has some terrific features -right now for me it is like seeing only the tip of iceberg.
Aug 04 2021