Достаточно очевидный способ сделать что-то вроде этого - определить хвостовую рекурсивную l oop внутри любых локально определенных функций, которые вы хотите:
(defun eps-closure (initial-states transition-rule)
(flet ((trace-eps-onestep (states)
(remove-duplicates
(flatten
(append
states
(mapcar
(lambda (state) (transition-state state :eps transition-rule))
states))))))
(labels ((eps-closure-loop (states)
(let ((next (trace-eps-onestep states)))
(if (set-difference next states)
(eps-closure-loop states)
next))))
(eps-closure-loop initial-states))))
Теперь совершенно ясно, что существует только одно определение trace-eps-onestep
. Обратите внимание, что я также воспользовался возможностью удалить второй аргумент из всех вызовов, поскольку это всегда один и тот же объект, и я переименовал аргументы, чтобы сделать, надеюсь, больше смысла.
Мне нравится этот вид трюка big-global-definition-with-a-bunch-of-local-functions-внутри этого трюка, поскольку это означает, что из чтения кода совершенно ясно, что они являются вспомогательными функциями только для использования глобальной функцией.
В этом конкретном случае trace-eps-onestep
вызывается ровно из одного места и на самом деле вообще не имеет причин для существования. Хороший компилятор, вероятно, полностью его оптимизирует, но я думаю, что следующий код в любом случае более понятен:
(defun eps-closure (initial-states transition-rule)
(labels ((eps-closure-loop (states)
(let ((next (remove-duplicates
(flatten
(append
states
(mapcar
(lambda (state)
(transition-state state :eps transition-rule))
states))))))
(if (set-difference next states)
(eps-closure-loop next)
next))))
(eps-closure-loop initial-states)))
Наконец, такая хвостовая рекурсивная локальная функция не очень естественна в CL ( хотя я очень часто программирую вот так!): мне кажется, что-то вроде следующего более понятно:
(defun eps-closure (initial-states transition-rule)
(loop for states = initial-states then next
for next = (remove-duplicates
(flatten
(append
states
(mapcar
(lambda (state)
(transition-state state :eps transition-rule))
states))))
if (null (set-difference next states))
return next))
Я не тестировал ни одну из этих функций (все они компилируются, но определения отсутствуют).