2012-02-25 39 views
4

按照V8票,它說,因爲它是在現實世界 使用JavaScript和尾調用

尾調用消除不兼容JavaScript。考慮以下幾點:

function foo(x) { 
    return bar(x + 1); 
} 

function bar(x) { 
    return foo.arguments[0]; 
} 

foo(1) 

這將返回1.

它沒有解釋清楚,如果JavaScript支持尾調用,這將是什麼富(1)爲什麼值?

任何人都可以解釋一下嗎?

+1

等等,那有效?哇。 – Ryan 2012-02-25 17:49:33

+1

僅供參考,http://markmail.org/message/tzlbsdo2tvxy7q4f – 2012-02-25 18:06:04

回答

2

It didn't explain clearly what if JavaScript support tail call, what would be the value of foo(1) and why?

值將1當你做foo(1)因爲foo函數返回bar功能和bar函數的結果也不過是讀foo功能與foo.arguments[0]第一個參數(arguments是隱含可用對象的每一個功能,用於讀取傳遞給函數的參數)並返回它。的foo第一個參數恰好是1當你這樣做:

foo(1); 

這裏是擊穿:

function foo(x) { 
    return bar(x + 1); // foo calls bar function which returns 1 
} 

function bar(x) { 
    return foo.arguments[0]; // bar reads first argument passed to foo which is 1 
} 

foo(1); // 1 is x in foo function 

bar函數只是讀取foo第一個參數(通過foo.arguments[0])並返回,因爲其中沒有添加完成。

4

這值得一點解釋。談話開始像這樣(格式化代碼):

If I open the JavaScript console in Chrome and write this:

function fac(n, a) { 
    if (n == 0) { 
     return a; 
    } 
    else { 
     return fac(n - 1, a * n); 
    } 
} 
fac(100000, 1); 

I get this: RangeError: Maximum call stack size exceeded

I think V8 might be a nice target virtual machine for other programming languages if it supported tail calls. It's the only big obstacle I can see for languages with functional features.

如果你測試代碼,你會發現,fac作品低值,返回Infinity更高的價值,並導致瀏覽器拋出一個RangeError(最大通話堆棧大小超過),甚至更高的值。

其原因是從另一個函數中調用的每個函數都被添加到「調用堆棧」中,這涉及一些內存開銷。有了足夠的遞歸,環境就會耗盡內存。


這是通過「tail call elimination」在其他語言中工作,或者不需要將調用添加到調用堆棧。例如,類似於函數的東西可以存在與普通函數不同的地方,因爲它們在返回時會導致調用函數返回。這可以消除添加到調用堆棧的需要,這意味着遞歸本質上可以是無限的。請參閱Wikipedia上的tail call文章以獲得深入解釋。

對上述消息的響應只是爲什麼tail-call消除(將函數從調用堆棧中刪除)與其他功能(Function#arguments)不兼容的原因提供的,這些功能可以是非標準功能。

1

爲了清楚起見,tail call elimination是一種節省堆棧空間的優化技術,對於遞歸尤其有用。當函數以另一個函數調用結束時,尾部調用消除可以避免分配另一個棧幀來調用被調用的函數。相反,它會重用(銷燬和重新調用)調用函數的堆棧幀,因爲它(可能)不再需要。但是,該示例顯示JavaScript代碼可能仍需要調用者的堆棧框架。

It didn't explain clearly what if JavaScript support tail call, what would be the value of foo(1) and why?

如果尾調用消除了支持,對foo調用的信息將使得尾部調用bar時遭到破壞,因此foo.arguments[0]將是一個錯誤。如果給定的代碼正常工作,則尾部呼叫消除是不可能的。