Как я могу проверить ограничения стека и выполнить рекурсию стиля Chicken Scheme в Java?

Рассмотрим следующий код. Этот код почти реализует рекурсию в стиле Chicken Scheme, где большую часть времени функции вызываются напрямую, но иногда есть более сложная процедура трамплина. Однако код работает не совсем корректно. Что мне действительно нужно, так это метод stackLimitsAlmostReached, который возвращает логическое значение, указывающее, существует ли опасность переполнения стека. Как я могу проверить ограничения стека и выполнить рекурсию в стиле Chicken Scheme в Java?

import java.util.Scanner;

public class Main {

public static abstract class Thunk {
    public abstract Thunk x();

    public final void run() {
        Thunk ip = this;

        while (ip != null)
            ip = ip.x();
    }
}

public static void main(String[] unused) {
    final Scanner scanner = new Scanner(System.in);

    new Thunk() {
        public Thunk x() {
            System.out.println("Hello World!");

            try {
                return this.x();
            } catch (StackOverflowError t) {
                System.out.println("GC!");
                scanner.nextLine();
                return this;
            }
        }
    }.run();
}
}

person Molossus Spondee    schedule 13.09.2012    source источник
comment
Таким образом, реальный вопрос заключается в проверке того, сколько места осталось в стеке, а не в рекурсии, Курице или Схеме?   -  person Jim Garrison    schedule 14.09.2012
comment
@JimGarrison Вопрос не связан с Chicken Scheme, но я чувствую, что некоторые энтузиасты (и определенно разработчики, которые работали над кодом для хвостовой рекурсии) Chicken Scheme, вероятно, имели бы опыт работы со стеками в C, а также могли бы попытаться выполнить подобные вещи в Java. В частности, я предполагаю, что следующий разговор мог произойти в дальних уголках Интернета, недоступных для Google. Джо: Почему бы не портировать Chicken Scheme на Java? Боб: Это было бы много работы и не имело бы смысла. Кроме того, я проверил, и нет возможности проверить размер стека во время выполнения.   -  person Molossus Spondee    schedule 06.10.2012


Ответы (1)


Эй, возможно, я неправильно понял ваш вопрос, но я думаю, что вы должны сначала искать эти параметры (мудрый Java, но это не проблема, IMO)

-ss Stacksize to increase the native stack size or

-oss Stacksize to increase the Java stack size,

Собственный размер стека по умолчанию — 128 КБ с минимальным значением 1000 байт. Размер стека Java по умолчанию составляет 400 КБ с минимальным значением 1000 байт.

Но я действительно чувствую, что должен предупредить вас о том, что JVM не может поддерживать оптимизацию хвостовых вызовов из-за своей модели безопасности. Википедия . Каждый раз, когда вы вызываете одну и ту же функцию, вы вводите новый кадр стека, и поэтому вы быстро работаете с ограничениями. Правильная схема, поддерживающая TCO, на самом деле не создает новый кадр стека, а просто обновляет значения и возвращается к продолжению в начале текущего кадра. это делает рекурсию очень эффективной.

Даже clojure, который работает на JVM, страдает от этой проблемы, поэтому у него есть лямбда, называемая recur, для обработки этого ограничения. проверьте также: документ ТШО

person ramrunner    schedule 15.09.2012
comment
Каждый раз, когда функция вызывает себя, выделяется новый кадр стека? Это действительно плохо. Таким образом, полное игнорирование проблемы переполнения стека (это то, что я хотел обойти в первую очередь), означает ли это, что функция, вызывающая сама себя, менее эффективна, чем использование трамплинов (как, по-видимому, делает Clojure?) - person Molossus Spondee; 06.10.2012