Нет, этого нельзя сделать, не изменив сигнатуру определяемых вами функций (или, возможно, используя какую-то волосатую вещь, которая переопределяет макроразложение): у вас есть то, что я называю «несоответствием импеданса распространения / nospread», которое не может разрешается стандартным макросом в CL.
Функция nospread - это функция, которая упаковывает все свои аргументы в один формальный. Функция «распространение» имеет один формальный аргумент. Я выучил эти термины при использовании InterLisp: они могут предшествовать этому, но сейчас они в основном не используются. Функции CL могут быть только частично распакованными ((foo bar &rest more)
). Ваш foo
является nospread.
A рассогласование импеданса распространения / nospread происходит, когда у вас есть функция распространения, но вы хотите использовать функцию nospread, или наоборот . Это почти всегда признак проблемы дизайна. Обходной путь для проблем распространения / nospread обычно включает apply
.
Ваша проблема в том, что foo
- это nospread-функция: она превращает все свои аргументы в один список, но вы хотите, чтобы макрос обрабатывал ее как Функция распространения, передавая ей один список аргументов.
В частности, в CL выражение, подобное (x (y ...))
, никогда не может быть превращено в (x a1 a2 ...)
для любой y
, функции или макроса (но см. ниже) и это то, что вам нужно.
В вашем случае вы хотите, чтобы что-то вроде
(foo (expand bar a b ...)
превратилось в
(foo (bar a) (bar b)
И этого не может быть .
Были Лиспы, у которых были вещи, которые назывались «сплайсинговыми макросами», в которых расширение макроса можно было «сплайсировать» в список, как это делает ,@
для обратной цитаты. Может случиться так, что для CL существуют макрокоманды сращивания, а может быть и то, что они переносимы: вы можете получить длинный путь с *macroexpand-hook*
. Но стандартные CL-макросы не могут этого сделать.