Может ли кто-нибудь объяснить мне следующий фрагмент кода? Я понимаю, что делает каждая маленькая деталь, но не могу понять, как они работают вместе Функция получает список, например:
(1 2 (3 (4 5) (6 7)) 8 (9 10))
который имеет 5 подсписков и возвращает список всех подсписков:
((1 2 (3 (4 5) (6 7)) 8 (9 10)) (3 (4 5) (6 7)) (4 5) (6 7) (9 10))
Код:
(defun all_sublists (l)
(cond
((atom l) nil)
(T (apply 'append (list l) (mapcar 'all_sublists l)))
)
)
Я понимаю, что первое условие говорит, что если l является атомом, возвращается nil, но не могли бы вы объяснить мне, что делает вторая строка? Почему это Т, которое я понимаю, означает Истина, и можете ли вы объяснить мне это как можно проще?
all_sublists
— типичная рекурсивная функция. При анализе такой рекурсивной функции мы можем действовать следующим образом:
Прежде чем рассматривать эту реализацию функции, мы предполагаем, что она правильная. Так что же это за функция? Нам сказали, что он принимает список, содержащий подсписки, и возвращает новый список с конкатенацией исходного списка со всеми его подсписками (рекурсивно, поэтому, если внутренний подсписок содержит другие подсписки, они возвращаются вместе с внутренним подсписком). Итак, мы предполагаем, что это правда, и смотрим на функцию.
Первая строка проста для понимания: в случае пустого списка, то есть списка без элементов, ни атома, ни подсписков, мы возвращаем nil
, который на самом деле является самим списком, и это соответствует определению функция.
Чтобы понять вторую строку, мы начнем с внутреннего выражения. Итак, что значит (mapcar 'all_sublists l)
? mapcar
возвращает список, полученный объединением результатов применения определенной функции ко всем элементам списка. Здесь мы применяем all_sublists
ко всем элементам l
, поэтому мы возвращаем список, содержащий результаты всех таких приложений: другими словами, результаты применения all_sublists
к каждому элементу l
. Когда элемент является атомом, он возвращает nil
, а если элемент является списком, он возвращает список, полученный путем объединения такого элемента со всеми его подсписками (мы уже знаем, что возвращает all_sublists
!). Таким образом, возвращается список со всеми этими результатами. Теперь посмотрите на внешнее выражение: (apply 'append (list l) the-result-of-mapcar)
. apply
применяет функцию (в данном случае append
) к списку аргументов. Итак, в этом случае мы добавляем к списку, содержащему уникальный элемент, исходный список l
, the-result-of-mapcar
. Таким образом, мы получаем список, состоящий из l
и всех его подсписков, рекурсивно созданных функцией.
И последнее замечание: это кажется в некотором роде «магическим» или, может быть, «абсурдным». Не расстраивайтесь, если изначально вы не совсем понимаете это. У всех нас было одно и то же ощущение. Но если вы упорно пытаетесь понять этот вид рекурсии, вы, в конце концов, добьетесь успеха!
большое спасибо, что помогли мне понять это