Вот две реализации факториала с этого сайта:
Оптимизированный хвостовой вызов (TCO):
function fact(n) {
return tail_fact(n,1) ;
}
function tail_fact(n,a) {
if (n == 0)
return a ;
else
return tail_fact(n-1,n*a) ;
}
И тот, который переписан в стиле программирования продолжения (обратный вызов):
function fact(n,ret) {
tail_fact(n,1,ret) ;
}
function tail_fact(n,a,ret) {
if (n == 0)
ret(a) ;
else
tail_fact(n-1,n*a,ret) ;
}
Похоже, что в учебнике предполагается, что вторая версия также является TCO, но последнее, что возвращает вторая версия, это undefined
, и ее вызов не находится в хвостовой позиции в соответствии с это руководство.
Однако также кажется, что return
здесь вообще не используется, и, следовательно, нет необходимости создавать новый кадр в стеке с адресом для возврата. Так это то, что делает вторую реализацию TCO?
--harmony_tailcalls
не считает второй действительным для TCO. Аксель Раушмайер говорит нет, это не хвостовой вызов, потому что после него стоит неявныйreturn undefined;
. Я не уверен, что верю этой логике (но несогласие с Акселем Р. на самом деле очень нервирует меня); JS проводит различие между выходом из функции безreturn
иreturn;
илиreturn undefined;
, хотя результат их вызова одинаков. В какой-то момент я достану свой мачете и возьму на спек... - person T.J. Crowder   schedule 10.04.2017tail_fact
какvoid
(неопределенный), мы могли бы тривиально увидеть, чтоreturn
ничего не меняет (по-прежнему возвращает неопределенное) и что вызов находится в хвостовой позиции. К сожалению, у нас нет статических типов в JS, поэтому вам нужно явно добавитьreturn
и надеетесь, что он всегда возвращает undefined… - person Bergi   schedule 10.04.2017return <constant>
после местоположения возврата, и когда следующий кадр стека делает то же самое, он знает, что возвращаемое значение будет проигнорировано, и может избежать создания внутреннего стека. кадры. Но, конечно же, спецификация ES6 этого не требует… - person Bergi   schedule 10.04.2017Node
не считает второй действительным для совокупной стоимости владения? - person Max Koretskyi   schedule 10.04.2017JS
не гарантируется, верно? - person Max Koretskyi   schedule 10.04.2017fact(1e6, result => console.log(result))
и получив исключение переполнения стека. :-) А вот с первым - нет. Это вариант теста kangax для поддержки совокупной стоимости владения здесь. - person T.J. Crowder   schedule 10.04.2017