d为啥要用全名
原文
有个把标准库的std.traits.fullyQualifiedName
转化为__traits(fullyQualifedName)
的请求.因为Phobos
实现扩展了很多模板
,所以想法
是通过在编译器
中实现
它来减少
编译时间.然而,亚当
认为不应使用它,定义很差,且很容易错误地元编程.
因此问题是:你是否用std.traits.fullyQualifiedName
,如果用,用它来做什么?
相关链接:1,2
我不用全名,有带整合属性的__traits
和typeid
对我已足够了.
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
,可打印它为Nullable
或Nullable!int
,否则此时,它打印带模块名的std.typecons.Nullable
来澄清
.对错误消息
,编译器有知识
和现有代码
.因此,公开
它可能会有些价值.
在D类外创建网络API
和用户接口
?没有全名
.
用D声明创建脚本
语言绑定?没有全名
.
从D接口创建动态库加载器
?没有全名
.
在D和Java
或C#
代码之间创建双向桥梁
?无全名
.
自定义
单元测试?无全名
.
从XML
映射D模块到实例化
类?没有全名
.
自定义
事件循环
消息框,接受类型
并分发
它们?不需要全名
.
根据具体
情况使用.mangleof
或typeid()
,这就是dmd
和druntime
干的.
从标识
中产生部分全名
,一般它更可读.这就是dmd
干的.
:避免因为生成
的代码中导入
而导致名字冲突
使用本地名
,这不是问题
.如果看到冲突
,表明你正在与语言
斗争,而不是使用更好
方法来合作
.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现