Новая версия сайта, доступна здесь.
Рекурсии, урок 2
Возьмем последний пример из первого урока. Там из списка с числами получался список 3D точек, но бывают случаи, когда нужны только 2D точки. Тогда этот код будет выглядеть так:
(setq lst '(1 2 3 4 5 6 7 8 9)) (defun rec_lst_2d (lst) (if lst (cons (list (car lst) (cadr lst) ) ;_ list (rec_lst_2d (cdddr lst)) ) ;_ cons ) ;_ if ) ;_ defun
Вызывать:
(rec_lst_2d lst)
получаем
'((1 2) (4 5) (7 8))
И наконец, то же самое, но для списка 2D точек, их можно получить после Vla-Get-Coordinates отличие в том, что количество элементов — чётное.
(setq lst '(1 2 3 4 5 6 7 8)) (defun rec_lst_2d_pt (lst) (if lst (cons (list (car lst) (cadr lst) ) ;_ list (rec_lst_2d_pt (cddr lst)) ) ;_ cons ) ;_ if ) ;_ defun
Вызывать:
(rec_lst_2d_pt lst)
получаем
'((1 2) (3 4) (5 6) (7 8))
Надеюсь, что после всех приведенных функций, уже не составит большого труда понять сам алгоритм и сделать рекурсию с простым перебором элементов. Рассмотрим вариант использования функции рекурсии для создания списка. Допустим, у нас есть два числа 5 и 8, необходимо получить список, последовательно заполненный цифрами, начиная с 5 и заканчивая 8 с шагом 1 Нужно получить:
'(5 6 7 8)
Рекурсия:
(defun rec_2i_lst (a b) (if (<= a b) (cons a (rec_2i_lst (1+ a) b)) ) ;_ if ) ;_ defun
Вызывать:
(setq a 5 b 8) (rec_2i_lst a b)
Разберем, как она работает. Поскольку, мы объявляем A B как аргументы, вне функции они остаются неизменными, но внутри нее, мы можем их изменять! Значит можно организовать цикл с условием:
(<= a b)
и после каждого добавления в список элемента будем увеличивать A
(1+ a)
до тех пор, пока условие выполняется. На этот раз я не буду разворачивать код, а покажу вычисления, для каждого цикла и вместо переменных вставлю их значения: цикл 1:
(if (<= 5 8) (cons 5 (rec_2i_lst (1+ 5) 8)) ) ;_ if
результат:
'(5 6 7 8)
цикл 2:
(if (<= 6 8) (cons 6 (rec_2i_lst (1+ 6) 8)) ) ;_ if
результат:
'(6 7 8)
цикл 3:
(if (<= 7 8) (cons 7 (rec_2i_lst (1+ 7) 8)) ) ;_ if
результат:
'(7 8)
цикл 4:
(if (<= 8 8) (cons 8 (rec_2i_lst (1+ 8) 8)) ) ;_ if
результат:
'(8)
цикл 5:
(if (<= 9 8) (cons 9 (rec_2i_lst (1+ 9) 8)) ) ;_ if
результат:
NIL
Формирование списка получается так:
(cons 5 (cons 6 (cons 7 (cons 8 nil ) ;_ cons ) ;_ cons ) ;_ cons ) ;_ cons