Существует также LISP чувство «батут», как описано в Википедии:
Используется в некоторых реализациях LISP, батут цикл, который итеративно вызывает санк возвращающих функции. A одного батута достаточно для выразить все управляющие передачи программы ; такая выраженная программа батут или в стиле «батут»; конвертировать программу в батут стиль батут. Trampolined функция может быть использована для реализации хвоста рекурсивной функция вызывает в стеке-ориентированных языках
Допустит, мы используем Javascript и хотим написать наивную функцию Фибоначчей в продолжении обходя стиль. Причина, по которой мы это сделаем, не имеет значения - например, для схемы портов для JS или для игры с CPS, которую мы должны использовать в любом случае для вызова функций на стороне сервера.
Таким образом, первая попытка
function fibcps(n, c) {
if (n <= 1) {
c(n);
} else {
fibcps(n - 1, function (x) {
fibcps(n - 2, function (y) {
c(x + y)
})
});
}
}
Но работает это с n = 25
в Firefox выдает ошибку 'Слишком много рекурсии!'. Теперь это точно проблема (отсутствие оптимизации хвостового вызова в Javascript), который решает батут. Вместо того, чтобы делать (рекурсивный) вызов функции, дайте нам return
инструкцию (thunk) для вызова этой функции, которая будет интерпретироваться в цикле.
function fibt(n, c) {
function trampoline(x) {
while (x && x.func) {
x = x.func.apply(null, x.args);
}
}
function fibtramp(n, c) {
if (n <= 1) {
return {func: c, args: [n]};
} else {
return {
func: fibtramp,
args: [n - 1,
function (x) {
return {
func: fibtramp,
args: [n - 2, function (y) {
return {func: c, args: [x + y]}
}]
}
}
]
}
}
}
trampoline({func: fibtramp, args: [n, c]});
}
[Относящиеся] (http://stackoverflow.com/questions/2420346/c-api -function-callbacks-in-c-member-function-code) – bobobobo 2010-10-12 12:26:03
Это основная обобщенная форма некоторой функциональности, которую вы могли бы реализовать с помощью setjmp/lomgjmp, а именно, чтобы избежать стека ovwerflow. – Ingo 2013-07-11 15:51:23