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

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

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

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

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

textual
Листинг программы
  1. (defn g (l)
  2.     (defn go (l i)
  3.         (cond (null? l) nil
  4.             ((def x (car l))
  5.             (def y (cond (= 0 (mod i 2)) (/ x 2) (* x x)))
  6.             (printLn (str i "-th element was: " x ", now: " y))
  7.             (cons y (go (cdr l) (+ i 1)))) ))
  8.     (go l 1))
  9.  
  10. (printLn (g '(1 2 3 4 11 22 33 44 55 66)))
  11.  
  12. ...........
  13.  
  14. (1 -th element was:  1 , now:  1)
  15. (2 -th element was:  2 , now:  1)
  16. (3 -th element was:  3 , now:  9)
  17. (4 -th element was:  4 , now:  2)
  18. (5 -th element was:  11 , now:  121)
  19. (6 -th element was:  22 , now:  11)
  20. (7 -th element was:  33 , now:  1089)
  21. (8 -th element was:  44 , now:  22)
  22. (9 -th element was:  55 , now:  3025)
  23. (10 -th element was:  66 , now:  33)
  24. (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

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы