Разобраться в ошибке - Lisp (229492)
Формулировка задачи:
(defun f(x)(if (> x 0) T nil));;предикат выводящий Т если число больше нуля,в противном случае Nil
(defun pos (x L);;функция находящая позицию(индекс) элемента в списке
(if (eq (car L) x) 0 (+ 1 (pos x (cdr L)))))
(defun spisok_pozich(L f pos);;главная функция
(
cond ((null l) nil)
(t
((f(car l) T) (cons (pos(carl L)) (spisok_pozich((cdr L) f pos))))
)))Решение задачи: «Разобраться в ошибке»
(defun spisok_pozich(L f &optional (n 0)) (cond ((null l) nil) ((funcall f (car l)) (cons n (spisok_pozich (cdr L) f (+ 1 n)))) (t (spisok_pozich (cdr L) f (+ 1 n))))) ==> spisok_pozich (spisok_pozich '(1 -2 9 -5 2) 'f) ==> (0 2 4)
Объяснение кода листинга программы
В данном коде определенная функция spisok_pozich принимает три аргумента: список L, функцию f и опциональный аргумент n со значением по умолчанию 0.
Если список L пуст, то возвращается nil.
Если функция f применительно к первому элементу списка L возвращает не nil, то возвращается новая функция, которая вызывается с аргументами (cdr L) (то есть, список без первого элемента), f и n + 1.
Если первый элемент списка L не удовлетворяет условию выше, то вызывается рекурсивно spisok_pozich с аргументами (cdr L) (то есть, список без первого элемента), f и n + 1.
Таким образом, если применить spisok_pozich к списку (1 -2 9 -5 2) и функции f, которая возвращает 2 при делении на 2 и 0 в противном случае, то вернется список (0 2 4). Это означает, что функция f вернула 2 при делении на 2 первого элемента списка (1 -2 9 -5 2), после чего была вызвана рекурсивно с аргументами (cdr L) (то есть, список без первого элемента) и n + 1 (то есть, 2 + 1 или 3). Поскольку второй элемент списка также удовлетворяет условию, то рекурсия продолжилась, и в итоге был возвращен список (0 2 4).