d为啥要用全名

原文
有个把标准库的std.traits.fullyQualifiedName转化为__traits(fullyQualifedName)的请求.因为Phobos实现扩展了很多模板,所以想法是通过在编译器实现它来减少编译时间.然而,亚当认为不应使用它,定义很差,且很容易错误地元编程.
因此问题是:你是否用std.traits.fullyQualifiedName,如果用,用它来做什么?
相关链接:1,2

我不用全名,有带整合属性的__traitstypeid对我已足够了.

class S
{
    short n;
    alias n this;
    this(short n) { this.n = n; }
}

void print(alias T)()
{
    import std.stdio : writeln;
    TypeInfo name = typeid(T);
     name.writeln;

    import std.traits : fullyQualifiedName;
    
    fullyQualifiedName!T.writeln;
    T test = [ new S(41), new S(42) ];
    __traits(getPointerBitmap, S).writeln(": ", test);
}

void main() {
    alias arrS = const S[];
    print!arrS;

    class S { short s; }
    auto test = new S;

    assert(__traits(getPointerBitmap, S) == [32, 8]);
    assert(is(
        typeof(S.s) == short)
    );
} /*
const(const(onlineapp.S)[])
const(onlineapp.S[])
[18, 0]: [const(onlineapp.S), const(onlineapp.S)] //*/

哦,还有该

struct Str
{
  alias ToString this;
  size_t s;
  string ToString() const
  {
   import std.conv : text;
   return text(s);
  }
}
enum Params { width= 100 }
auto String = Str(Params.width);
import std.conv;

void main()
{
  string[] data;
  data ~= __traits(identifier, String);
  data ~= typeof(String).stringof;
  data~= String;
  data ~= Params.width.to!string;
 data.writeln; // ["String", "Str", "100", "width"]
}

D给了我创造大世界一切.

亚当:不应使用fullyQualifiedName来查找符号
但是我坚信他错了,他说它不应,它应该,它需要,它是基本自省能力.
我在后两个方面使用它:
1)唯一标识一个类型(注册类型来序化,或传递到哈希函数等)(.a).
2)对调试来说,打印效果很好..b.

:.a.
编译器使用.mangleof来实现该目的,而druntime使用typeid().全名只是mangleof更大但并不独特的表示.
:.b
很简单就可实现(包括非常快地切换mangleof).
那么为什么Phobos实现会如此复杂呢?嗯,有些是不必要的复杂,但大部分是与各种不同类型模板参数有关(其余大部分是因为函数重载).这些参数也可从mangleof中提取,我在github线程中说过,但很多时候这些参数损害了可读性.

调试,你很可能更愿意部分全名+源码位置,它更能帮助调试:

random.d:1081 std.random.Mt19937
//对比
std.random.MersenneTwisterEngine!(uint, 32, 624, 397, 31, 0x9908b0df, 11, 0xffffffff, 7, 0x9d2c5680, 15, 0xefc60000, 18, 1_812_433_253)

(标准库PR中的特征选择了后者.)
现在,我承认这有点不公平,因为编译器再也不公开别名了.但:

random.d:1081 std.random.MersenneTwisterEngine

不带参数更有利于调试.这是简单示例.
PR线程中,我提出:

structFromTable!(import("db.sql"), "MyTable");

源码中的这种表示还算不错.定义点非常可读.假定转储全名屏幕上,有几万字节.这有用吗?

别名trait更有用!至少全局别名是这样;像

template a(alias A) {}

局部变量总是返回不是很有趣的A,但是如果在外部域别名名字,这确实是有价值的信息.
现在,我承认模板参数有时是有用的:

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

如果只按'std.typecons.Nullable'打印了类型,你就遗漏了.怎么知道哪个值得打印?要看情况,这表明最好用库代码来完成.

同时,编译器还可用它的知识消歧.
除非中有另一个Nullable,可打印它为NullableNullable!int,否则此时,它打印带模块名的std.typecons.Nullable澄清.对错误消息,编译器有知识现有代码.因此,公开它可能会有些价值.

在D类外创建网络API用户接口?没有全名.
用D声明创建脚本语言绑定?没有全名.
从D接口创建动态库加载器?没有全名.
在D和JavaC#代码之间创建双向桥梁?无全名.
自定义单元测试?无全名.
XML映射D模块到实例化类?没有全名.
自定义事件循环消息框,接受类型分发它们?不需要全名.
根据具体情况使用.mangleoftypeid(),这就是dmddruntime干的.
标识中产生部分全名,一般它更可读.这就是dmd干的.
:避免因为生成的代码中导入而导致名字冲突
使用本地名,这不是问题.如果看到冲突,表明你正在与语言斗争,而不是使用更好方法来合作.

posted @   zjh6  阅读(18)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示