天天看點

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​

​​不适合做​

​該回溯​

​​,會非常慢,是以​

​一般​

​​不會​

​修複​

​.