d递归和属性推导
原文
我遇见歧义了.
float recurse()(float val, float till)
{
return val < till? recurse(val * 2, till): val;
}
@safe void main()
{
import std;
writeln(recurse(1.5, 40.0));
writeln(typeid(&recurse!()));
}
//编译并打印:
48
float function(float, float) pure nothrow @nogc @safe*
但规范说,不会按@安全或纯及不抛推导递归函数.
实现和规范,哪个对?
我倾向实现是正确的,因为代码并没有违反内存安全.
丹尼斯正在研究使@安全推导对递归函数也是正确的,所以未来可能会完全取消该限制.
当函数直接调用自身时,忽略对该调用的属性检查.
然而,当两者间有多个函数时,推导就会变成"我正在调用现在不能完成属性推导函数,所以保守地假设不能按@安全推导所有属性.",似乎规范已修改为记录实现的该缺点.
我希望可简单地假定已推导所有属性,使如下工作:
void fun1()() { fun2(); }
void fun2()() { fun1(); }
void main() @safe pure nothrow @nogc
{
fun1(); // 当前失败
}
但这里有个更麻烦情况:
@system void systemFunc();
void fun1()()
{
alias T = typeof(fun2());
systemFunc();
}
void fun2()()
{
fun1();
}
void main0() @system
{
fun1();
}
void main() @safe
{
fun2(); // 非系统!
}
编译器分析fun1,然后fun2,然后需要决定调用fun1是否是安全的.
如果它假定为是的,安全.则稍后当它看到调用系统函数(systemFunc)()时,需要返回并标记函数2()为@系统,并重新分析,T现在是@系统的fun1.
DMD不适合做该回溯,会非常慢,所以一般不会修复.
但是,在缺少typeof()和其他函数类型依赖关系时,可维护每个函数的被调列表,以通过简单函数调用来解决最常见相互函数依赖关系.
我同意.我认为不应该有回溯,因为即使对所有约束有一致的方法,它也一般不会终止.
这里,如果在推导属性的同时,被迫决定属性,那么没有明显的默认值会很烦人.我想可在继承类型``推迟中解析它们,并适当地耦合推导,但不知道是否值得,似乎用模板实例化难以正确+高效,因为可能以后会改参数类型.
浙公网安备 33010602011771号