Лексические замыкания и рекурсия (ну или итерация) - Lisp

Узнай цену своей работы

Формулировка задачи:

Добрый день, All! продолжаю исследовать механизмы Lisp. возник вопрос, связанный с замыканием и ленивыми вычислениями. не могу понять, как организовать рекурсивно вызов функции, с некими переменными в своем собственном контексте. пример:
(defun car-begin (x) #'(lambda (str) (progn (setf x (1+ x)) (nth x str))))
(setf car-next (car-begin -1))
создаю функцию, которая последовательно перебирает элементы списка
[526]> (funcall car-next '(q w e r t y))
Q
[527]> (funcall car-next '(q w e r t y))
W
[528]> (funcall car-next '(q w e r t y))
E
[529]> (funcall car-next '(q w e r t y))
R
[530]> (funcall car-next '(q w e r t y))
T
[531]> (funcall car-next '(q w e r t y))
Y
[532]> (funcall car-next '(q w e r t y))
NIL
а теперь я пытаюсь многократно вызывать эту функцию до момента, пока список не окончен. пишу что-то вроде
(defun car-down (str)
  (cond ((funcall car-next str) (car-down str))
        (t nil)))
но это по понятным причинам (т.к. вызов функции в условии не выводит результатов) не работает. а как же быть? есть ли какие-либо способы? наиболее интересны конечно чисто функциональные методы. конечно можно и количество элементов посчитать и цикл организовать. но это не то, что хочется. хочется именно рекурсию с терминальной ветвью, когда функция выдаст nil. а чисто функционально, без progn (явного или неявного) что-то не удается сделать. или здесь принципиальная вещь? (сама-то моя функция car-next не чистая.)
что-то голова совсем не работает. все получилось почти:-)
(defun car-down (str)
  (if  (print (funcall car-next str)) (car-down str)))
[599]> (car-down '(q w e r t y))
 
Q 
W 
E 
R 
T 
Y 
NIL 
NIL
хотя, это и не то, что надо. дело в том, что потом я хочу собрать вывод в список. как-то коряво это будет получаться интересно, а есть ли Lisp-way?

Решение задачи: «Лексические замыкания и рекурсия (ну или итерация)»

textual
Листинг программы
(defn g (l)
    (defn go (l i)
        (cond (null? l) nil
            ((def x (car l))
            (def y (cond (= 0 (mod i 2)) (/ x 2) (* x x)))
            (printLn (str i "-th element was: " x ", now: " y))
            (cons y (go (cdr l) (+ i 1)))) ))
    (go l 1))
 
(printLn (g '(1 2 3 4 11 22 33 44 55 66)))
 
...........
 
(1 -th element was:  1 , now:  1)
(2 -th element was:  2 , now:  1)
(3 -th element was:  3 , now:  9)
(4 -th element was:  4 , now:  2)
(5 -th element was:  11 , now:  121)
(6 -th element was:  22 , now:  11)
(7 -th element was:  33 , now:  1089)
(8 -th element was:  44 , now:  22)
(9 -th element was:  55 , now:  3025)
(10 -th element was:  66 , now:  33)
(1 1 9 2 121 11 1089 22 3025 33)

Объяснение кода листинга программы

В этом коде на языке Lisp определена функция g, которая принимает список l в качестве аргумента. Внутри функции g определена вспомогательная функция go, которая рекурсивно обрабатывает элементы списка l. Когда функция go вызывается с начальным списком l и индексом i равным 1, она проверяет, является ли l null. Если это так, она возвращает nil. В противном случае она извлекает первый элемент x из l с помощью функции car. Затем она проверяет, является ли i четным числом с помощью оператора =. Если это так, она возвращает x/2. Если i нечетное, она возвращает x*x. В любом случае она печатает сообщение, используя функцию printLn, которая включает индекс i, старый элемент x и новый элемент y. Затем она добавляет y в новый список, который является результатом вызова функции cons, и передает новый список и i+1 в качестве аргументов в функцию go. Функция g вызывает функцию go с начальным списком l и индексом i равным 1. Пример использования функции g включает список [1 2 3 4 11 22 33 44 55 66], который передается в качестве аргумента в функцию g. Функция g печатает элементы списка, обработанные функцией go, в формате i-th элемент был: x, теперь: y, где i — это номер текущего элемента, x — это текущий элемент, а y — это результат его обработки. В результате получается [1 1 9 2 121 11 1089 22 3025 33].

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

10   голосов , оценка 4.2 из 5
Похожие ответы