LINUX.ORG.RU
ФорумTalks

Бесконечная рекурсивная функция


0

0

Как организовать её программными средствами? Можно делать что угодно, только бы она была бесконечной, т.е. могла вызывать себя бесконечное число раз. Подчёркиваю: именно бесконечное, ничем не ограниченное - ни размером стека, ни объёмом памяти. Видимо нужно организовать какую-то функцию от передаваемых аргументов, либо особым образом построить стек, либо лезть в ассемблер. Может есть готовые реализации подобной вещи? Вопрос исключительно интереса ради.

★★★★★

Если хвостовая, то можно... Кажется, call-with-current-continuation или как-то так.

shimon ★★★★★
()
Ответ на: комментарий от CrazyPit

Но ведь все эти вызовы будут заноситься в стек, и рано или поздно возникнет Stack overflow.

jcd ★★★★★
() автор топика
Ответ на: комментарий от jcd

если надо хранить все параметры - без ограничения в памяти не обойтись, если нет - обычный цикл то что тебе надо

lester ★★★★
()
Ответ на: комментарий от lester

надо хранить все параметры, и чтобы это и выглядело как функция, а не как её ассемблерная реализация. Может быть можно сделать функцию от переменных, или что-то вроде того?

jcd ★★★★★
() автор топика
Ответ на: комментарий от jcd

может тогда поможет man 'конечный автомат'?

если я правильно понял, что надо.

g
()
Ответ на: комментарий от vada

Абелева группа по первой операции, полугруппа по второй плюс дистрибутивность, или ты про что?

jcd ★★★★★
() автор топика
Ответ на: комментарий от jcd

Если компилятор поддерживает оптимизацию хвостовой рекурсии то нет. Он превратит такую рекурсию в итерацию на уровне ассемблера. GCC, например, оптимизирует.

CrazyPit ★★★
()

Хм. Любой алгоритм с рекурсией может быть переписан без нее.

Тут вопрос об объеме хранимых данных - что надо сохранять. Если только данные конечного ограниченого числа шагов - то можно сделать.

вот только как праивльно заметили компиляторы умеют оптимизировать сами только хвостовую рекурсию

namezys ★★★★
()
Ответ на: комментарий от CrazyPit

> Он превратит такую рекурсию в итерацию на уровне ассемблера

Хорошо, а если не поддерживает? Т.е. не будем использовать никаких компиляторных оптимизаций.

>Любой алгоритм с рекурсией может быть переписан без нее.


Тут собственно весь интерес в том - можно ли создать такую функцию, скажем, на С++, не прибегая при этом к возне с ассемблером.

jcd ★★★★★
() автор топика
Ответ на: комментарий от jcd

Задачка интересная. Я подумаю над ней, как будет время.

Но думаю что в виде функции нельзя. Хотя...

Объет вызывается на на стеке, а со спискаом

function a(): value->value;

function caller(function* f):
value val = 0;
while(1) val = f(val);

namezys ★★★★
()

Стесняюсь спросить, а какова конечная цель бесконечной рекурсии?
Рекурсия то тем и хороша что из нее выход есть.
"Спиберг... Ну не понятно, же!"

vada ★★★★★
()
Ответ на: комментарий от namezys

function a(): value->value;

хм, что-то вроде того, но тут точно ничего не будет в стек заноситься?

а какова конечная цель бесконечной рекурсии?

исключительно интереса ради.

jcd ★★★★★
() автор топика
Ответ на: комментарий от jcd

> хм, что-то вроде того, но тут точно ничего не будет в стек заноситься?

Что такое стек. Это способ сохранения данных. Вызовы можно организвать и другим путем. Я его привел.

Задача у тебя именно в сохранении коненчо числа шагов. То есть в терминах совремных архитектур, необходимо чтоб в стеке выполнения было конечное заранее ограничено число функций

namezys ★★★★
()
Ответ на: комментарий от jcd

Все одно не понятно. Организовать бесконечность запросто, но память и пр. ресурсы конечны. Это реальность. Срек кончится и фсё, или ОЗУ или ХДД.

vada ★★★★★
()
Ответ на: комментарий от namezys

>необходимо чтоб в стеке выполнения было конечное заранее ограничено число функций

Я бы даже сказал, что стек вообще не нужен, так как если что-то класть в него, то в пределе он всё равно переполнится.

>Организовать бесконечность запросто, но память и пр. ресурсы конечны. Это реальность.


Значит не будем использовать стек?

jcd ★★★★★
() автор топика
Ответ на: комментарий от jcd

>Значит не будем использовать стек?

Тогда остается GOTO
:)

vada ★★★★★
()
Ответ на: комментарий от jcd

>Но ведь все эти вызовы будут заноситься в стек, и рано или поздно возникнет Stack overflow.

Кольцевой буфер вместо стека

KRoN73 ★★★★★
()
Ответ на: комментарий от namezys

>любая рекурсия сводится к коду без функций

Не любая. Функции бывает нужно помнить свои локальные переменные/параметры.

madcore ★★★★★
()
Ответ на: комментарий от lester

Бесконечная рекурсия в общем виде требует бесконечного стека по определению, так что корректной быть не может. Или её разворачивать нужно, или стек ненужный не использовать... Собственно, бесконечная рекурсия полного отката назад по определению же не требует, так что стек можно и похерить :) И, вообще:

      call loop
      return
loop:
      pop eax
      ; do something
      call loop

Вот вам бесконечная рекурсия без переполнения стека :D

KRoN73 ★★★★★
()
Ответ на: комментарий от vada

Попробуй на бумаге посчитать (f 5), например.
Вот еще (для ценителей прекрасного):
((λ (x) (x x)) (λ (x) (x x))) - стек не используется.

power
()
Ответ на: комментарий от KRoN73

>Вот вам бесконечная рекурсия без переполнения стека :D

Ну этак каждый может. Чел на сях приплюснутых хотел... и без оптимизации от компилятора! :)

vada ★★★★★
()
Ответ на: комментарий от KRoN73

>Кольцевой буфер вместо стека

Тогда при возвращении можем получить не те значения переменных, которые заложили. Этот вариант по сути и нужно использовать, но "диаметром" кольца брать 1, для переменных строить какую-то математическую функцию, и при попытке возвращения функции назад, к предыдущей, - вычислять значения переменных и отдавать функции.

>Собственно, бесконечная рекурсия полного отката назад по определению же не требует, так что стек можно и похерить


Вот всё в этой стране так и происходит. Самая фишка состоит в том, что необходимо организовать полный откат назад, иначе неинтересно. :)

jcd ★★★★★
() автор топика
Ответ на: комментарий от jcd

Ну а в общем случае бесконечная рекурсия разумеется невозможна.

jcd ★★★★★
() автор топика
Ответ на: комментарий от power

Нет конечно. Хотя бы потому, что аргументами являются 2 числа, с которых надо начинать, а не номер числа, которое мы хотим получить.

Zenom ★★★
()
Ответ на: комментарий от madcore

> Не любая. Функции бывает нужно помнить свои локальные переменные/параметры.

Компьютер эквевалентен машине Тьюринга. Машину Тьюринга нерекурсивна. Дальше продолжать?

namezys ★★★★
()
Ответ на: комментарий от jcd

> Вот всё в этой стране так и происходит. Самая фишка состоит в том, что необходимо организовать полный откат назад, иначе неинтересно. :)

Тогда пожалусто назовите замое большое из натуральных чисел :)

namezys ★★★★
()
Ответ на: комментарий от Zenom

нет - но во многих практических задачах такое "колдунство" невозможно

lester ★★★★
()
Ответ на: комментарий от namezys

>Тогда пожалусто назовите замое большое из натуральных чисел :)

Гм, ну будем считать что счётчики у нас условно бесконечны, или реализуем длинную арифметику. Число, размер машинного представления которого приблизительно равен даже 32 байт, - это как бы очень большое число. Настолько большое, что нам не хватит винтов на этой планете под свопы, чтобы полностью вместить следы рекурсии, если мы в общем случае решим к нему приблизиться.

jcd ★★★★★
() автор топика
Ответ на: комментарий от Zodd

>void f(int n) return f(n); оно либо я чета не понял?

да, того что у тебя моментально переполнится стек.

jcd ★★★★★
() автор топика
Ответ на: комментарий от namezys

ну тебя смутило "возвращение из бесконечности", а я пояснил что в отношении счётчика для возвращения мы рассматриваем условную бесконечность (возможность счётчика вместе очень большое число), а в отношении самой функции - абсолютную.

jcd ★★★★★
() автор топика
Ответ на: комментарий от jcd

ОК, тогда кодируй стек в своем бесконечном счетчике. Получится очень даже забавно. Ушел от потребления бесконечного количества памяти, а пришел к бесконечному росту значения счетчика. В чем профит?

balodja ★★★
()

господи, даже в интерпретаторе можно

let f = f

потом запускаешь f.

yet_another_lor_account
()
Ответ на: комментарий от namezys

> Компьютер эквевалентен машине Тьюринга. Машину Тьюринга нерекурсивна. Дальше продолжать?

Продолжайте учить математическую логику. Конкретно - нумерацию Клини, тезис Чёрча, короче программу за первый курс университета.

your_bunny
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.