Mam funkcję rekursywną, która musi się powtarzać, dopóki nie znajdzie określonego wyniku. Jednak w ciele mojej funkcji po pierwszym rekursywnym wywołaniu mogę wykonać kilka innych obliczeń lub ewentualnie powtórzyć. Ale jeśli powrócę i znajdę wynik, którego szukam, to chciałbym po prostu przerwać rekurencję, którą robiłem i zwrócić ten wynik, aby uniknąć niepotrzebnych obliczeń.Powrót do wywołania najwyższego poziomu funkcji rekursywnej w Lisp
W zwykłym wywołaniu rekurencyjnym, gdy dojdziesz do "przypadku podstawowego", który zostanie zwrócony do funkcji, która wywołała, to zostanie zwrócona do tej, która go nazwała, i tak dalej. Chciałbym wiedzieć, jak powrócić do pierwszego uruchomienia tej funkcji i nie trzeba zwracać czegoś dla wszystkich pośrednich kroków.
Dla mojego podstawowego rekursji mógłbym napisać funkcję tak:
(defun recurse (x)
(if (= x 10)
(return-from recurse x)
(progn (recurse (+ x 1)) (print "Recursed!")))))
(recurse 1)
Został on napisany w celu zilustrowania tego, co mam na myśli o funkcja działa więcej obliczeń po rekurencyjnego wywołania. I, jak napisano, nie zwraca nawet wartości, którą interesuję, ponieważ wykonuję niektóre wydruki po zwróceniu wartości, na której mi zależy. (Uwaga: Polecenie return-from jest tutaj obce, ponieważ mógłbym po prostu napisać "x" na swoim miejscu, aby tam narysować paralele, gdy próbuję powrócić do rekursji najwyższego poziomu w moim drugim przykładzie poniżej.)
Teraz, jeśli chcę wyrzucić te dodatkowe "Powtórne!" wydruki Mogłem zamknąć wszystko w bloku, a następnie po prostu wrócić do tego bloku:
EDYCJA: Oto otoki funkcji dla mojego oryginalnego przykładu. Ten przykład powinien być teraz bardziej przejrzysty.
(defun recurse-to-top (start)
(block top-level
(labels ((recurse (x)
(if (= x 10)
(return-from top-level x)
(progn (recurse (+ x 1)) (print "Recursed!")))))
(recurse start))))
i działa ten blok leci aż 10 „znajduje się”, a następnie powraca do bloku z najwyższego poziomu bez nadruku obcego, tak jak chciałem. Ale wydaje się, że to bardzo chybiony sposób na uzyskanie tej funkcji. Chciałbym wiedzieć, czy istnieje standardowy lub "najlepszy" sposób na uzyskanie tego typu zachowania.
W twoim przykładzie z blokiem "Wycofane!" jest * nigdy * nie jest drukowane, więc dlaczego jest na pierwszym miejscu? Wierzę, że twój prawdziwy kod ma coś więcej do tego, co zostało utracone w twoim przykładzie. – uselpa
tj. '(Defun recurse (x) (if (= x 10) x (recurse (+ x 1))))' robi dokładnie to, co chcesz. – uselpa
Źle zrozumiesz moje pytanie. Celem wydruku wewnątrz mojej funkcji jest zademonstrowanie funkcji rekursywnej, która może wykonywać operacje po wywołaniu rekursywnym. W pierwszym przykładzie widać, że każda z funkcji drukowania uruchamia się, ponieważ zdarzają się po każdym powrocie rekurencji. Drugi przykład został napisany, aby pokazać potencjalny sposób obejścia tego problemu, powracając do najwyższego poziomu wywołania rekurencyjnego, nie wykonując żadnych dalszych poleceń. Zostawiłem tam polecenie drukowania, aby pokazać, że w tym przykładzie nie zostanie uruchomione. – Nyles