D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 4476 - __traits for more kinds of names
Summary: __traits for more kinds of names
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-07-16 16:44 UTC by bearophile_hugs
Modified: 2020-08-06 14:34 UTC (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description bearophile_hugs 2010-07-16 16:44:36 UTC
This is relative to page 22 of The D Programming Language.

This piece of D2 code shown in the book instantiates a class defined inside the current module named stats:
Object.factory("stats." ~ arg);

Generally in code it's better to apply the DRY principle, avoiding to duplicate information that later can get out of sync (in this case a change in the module name breaks the code inside the module).

This currently works (dmd v2.047), but it's not nice, and performs run-time computations for something that is known statically (maybe there are already better ways to do it):

Object.factory(split(to!string({class C {}; return new C;}()), ".")[0] ~ ".Foo");

The problem can be solved with few traits, able to tell at compile-time:
__traits(thisModuleName) : the name of the current module.
__traits(thisStructName) : the name of the current struct (where this line is contained), useful to create its toString that shows the struct name too.
__traits(thisClassName) : the name of the current class (this can be found with this.classinfo.name, but there is no need to compute it at runtime).
__traits(thisFunctionName) : the name of the current function, useful for CTFE & string mixins.

Possibly there are already ways to find such strings at compile-time, but having a simple standard way to do it is good (better than having magic variables like __function_name__). Some more power of static introspection can be very useful in D.
Comment 1 Heywood Floyd 2010-07-16 19:31:51 UTC
Just another workaround/hack:

module modulename;
class C{}
void main(){
	Object obj = Object.factory(.stringof[7..$] ~".C");
}
Comment 2 Gor Gyolchanyan 2011-07-28 08:08:18 UTC
(In reply to comment #0)
> This is relative to page 22 of The D Programming Language.
> 
> This piece of D2 code shown in the book instantiates a class defined inside the
> current module named stats:
> Object.factory("stats." ~ arg);
> 
> Generally in code it's better to apply the DRY principle, avoiding to duplicate
> information that later can get out of sync (in this case a change in the module
> name breaks the code inside the module).
> 
> This currently works (dmd v2.047), but it's not nice, and performs run-time
> computations for something that is known statically (maybe there are already
> better ways to do it):
> 
> Object.factory(split(to!string({class C {}; return new C;}()), ".")[0] ~
> ".Foo");
> 
> The problem can be solved with few traits, able to tell at compile-time:
> __traits(thisModuleName) : the name of the current module.
> __traits(thisStructName) : the name of the current struct (where this line is
> contained), useful to create its toString that shows the struct name too.
> __traits(thisClassName) : the name of the current class (this can be found with
> this.classinfo.name, but there is no need to compute it at runtime).
> __traits(thisFunctionName) : the name of the current function, useful for CTFE
> & string mixins.
> 
> Possibly there are already ways to find such strings at compile-time, but
> having a simple standard way to do it is good (better than having magic
> variables like __function_name__). Some more power of static introspection can
> be very useful in D.

Ha(In reply to comment #1)
> Just another workaround/hack:
> 
> module modulename;
> class C{}
> void main(){
>     Object obj = Object.factory(.stringof[7..$] ~".C");
> }

.stringof[7..$] is a 100% guarantee to get the module name, but if the module name coincides with anything inside it, problems will occur:

module main;

struct S
{
}

void main()
{
    mixin(`alias `~.stringof[7..$]~`.S MyStruct;`); // ERROR: function main does not have a struct in it
}

What i suggest is to have traits to get the aliases for the current module and current function. the current struct and class can be taken by typeof(this) and typeof(this).stringof. Thus the current function name will be accessible through __traits(thisFunction).stringof.
Comment 3 bearophile_hugs 2012-01-30 17:44:25 UTC
Another useful __traits is to find all classes in the given/current module.
Comment 4 Dmitry Olshansky 2018-05-17 15:02:17 UTC
Will likely be superseded by forthcoming introspection DIP.
Comment 5 Mathias LANG 2020-08-06 14:34:42 UTC
Nowadays we have `__traits(identifier)`  which gives you name.
There's also `std.traits.fullyQualifiedName`, and the `__MODULE__` token.
I think that fits all your use case, so closing as FIXED.