Why are you using `std.traits.fullyQualifiedName`?

Adam D Ruppe destructionator at gmail.com
Sat Jan 21 12:43:30 UTC 2023


On Saturday, 21 January 2023 at 05:21:15 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
> 1) Uniquely identifying a type (registration of types for 
> things like serializing, passing to hash function ext.).

the compiler uses .mangleof for this purpose and druntime uses 
typeid(). FQN is just an even bigger, but no more unique, 
presentation of mangleof.

> 2) Pretty printing for debugging. Here is some output that I 
> generated yesterday:
>
> - sidero.base.datetime.time.timezone.TimeZone(

This case is trivial to get out of existing language capabilities 
(including very, very quickly by slicing into mangleof).

Why is the Phobos implementation so complicated then? Well, some 
of it is unnecessary complexity, but much of it has to do with 
the various different kind of template arguments (and most the 
rest of it is due to function overloads). And these can again be 
extracted from mangleof, I said this in the github thread, but 
many times these actually harm readability.

For debugging, there's a good chance you'd actually rather have a 
partially qualified name tied together with a source location. 
Which is more likely to help debugging:

random.d:1081 std.random.Mt19937

or

std.random.MersenneTwisterEngine!(uint, 32, 624, 397, 31, 
0x9908b0df, 11, 0xffffffff, 7, 0x9d2c5680, 15, 0xefc60000, 18, 
1_812_433_253)

?

(Phobos and the trait in the PR picks the latter.)

Now, I'll grant this is a bit unfair because the compiler never 
exposes alias names anymore (though it used to, and I consider 
this a regression, it broke some of my code that used to reflect 
on those :( ). But even:

random.d:1081 std.random.MersenneTwisterEngine

without the arguments listed is better for debugging. And this is 
a simple one. In the PR thread, I mentioned 
`structFromTable!(import("db.sql"), "MyTable");` That 
representation in source isn't too bad. The definition point is 
pretty readable. The fullyQualifiedName is dozens of kilobytes 
dumped to the screen. Is this useful?

A trait to get the aliased name would be far more useful! At 
least the global aliased name; a local one like `template a(alias 
A) {}` always returning A not that interesting, but if the alias 
name is in an outer scope, that's actually valuable information.

Now, I will grant there are some places where template args help:

struct Thing {
   Nullable!int a;
   Nullable!string b;
}


If that just printed `std.typecons.Nullable` as the type, you are 
missing something. How do you know which one is worth printing 
and which one isn't? It probably depends... which means it is 
better done by library code.

At the same time, there is something the compiler can potentially 
do here, and again, I mentioned this in the PR thread: it could 
use its knowledge of scopes to disambiguate.

It could print this as Nullable or Nullable!int unless there's 
another Nullable in scope, in which case it prints the module 
name - std.typecons.Nullable - to clear it up. The compiler has 
the knowledge and the existing code to do this for error 
messages. So exposing it might be of some value.


But .... we need to identify the concrete intended use case. 
Error messages and debugging aren't even exactly the same and 
they're very different than code generation.

Just.... since we have the library capabilities to do all this 
with as much or as little customization as desired, does the 
language need to bloat it up offering a bunch of options?

But regardless, the one option it proposes to offer right now is 
not ideal for any use case.


More information about the Digitalmars-d mailing list