После долгого медитирования над макросами родилась маленькая задачка.
Напишите макрос на CommonLisp, который бы рекурсивно менял вхождения элемента в качестве функции в данном списке на заданную последовательность. То есть в случае исходного списка (foo 1 2 (foo 5 (foo 100 1000))), заменяемого элемента foo и заданной последовательности из одного элемента "+" должны получить форму (foo 1 2 (foo 5 (foo 100 1000))).
иными словами, если имя написанного макроса functional-replace должны наблюдать такую картину:
(macroexpand-1 '(functional-replace (foo 1 2 (foo 5 (foo 100 1000))) foo (+)))
результат: (+ 1 2 (+ 5 (+ 100 1000)))
соответственно форма (functional-replace (foo 1 2 (foo 5 (foo 100 1000))) foo (+))
должна быть интерпретирована в результат 1108
Здравствуйте, A13x, Вы писали:
Года 3 этим не занимался
(defmacro functional-replace (xs a b)
(cond ((null xs) nil)
((eq (car xs) a) `(apply
',b
(functional-replace ,(cdr xs) ,a ,b)))
((listp (car xs)) `(cons
(functional-replace ,(car xs) ,a ,b)
(functional-replace ,(cdr xs) ,a ,b)))
(t `(cons
,(car xs) (functional-replace ,(cdr xs) ,a ,b))) ))
[83]> (functional-replace (foo 1 2 (foo 5 (foo 100 1000))) foo +)
1108
A>Напишите макрос на CommonLisp, который бы рекурсивно менял вхождения элемента в качестве функции в данном списке на заданную последовательность. То есть в случае исходного списка (foo 1 2 (foo 5 (foo 100 1000))), заменяемого элемента foo и заданной последовательности из одного элемента "+" должны получить форму (foo 1 2 (foo 5 (foo 100 1000))).
A>иными словами, если имя написанного макроса functional-replace должны наблюдать такую картину:
A>A>(macroexpand-1 '(functional-replace (foo 1 2 (foo 5 (foo 100 1000))) foo (+)))
A>результат: (+ 1 2 (+ 5 (+ 100 1000)))
A>соответственно форма (functional-replace (foo 1 2 (foo 5 (foo 100 1000))) foo (+))
A>должна быть интерпретирована в результат 1108
A>
Здравствуйте, mryau, Вы писали:
M>Здравствуйте, A13x, Вы писали:
M>Года 3 этим не занимался
M>M>(defmacro functional-replace (xs a b)
M> (cond ((null xs) nil)
M> ((eq (car xs) a) `(apply
M> ',b
M> (functional-replace ,(cdr xs) ,a ,b)))
M> ((listp (car xs)) `(cons
M> (functional-replace ,(car xs) ,a ,b)
M> (functional-replace ,(cdr xs) ,a ,b)))
M> (t `(cons
M> ,(car xs) (functional-replace ,(cdr xs) ,a ,b))) ))
M>
M>M>[83]> (functional-replace (foo 1 2 (foo 5 (foo 100 1000))) foo +)
M>1108
M>
A>>Напишите макрос на CommonLisp, который бы рекурсивно менял вхождения элемента в качестве функции в данном списке на заданную последовательность. То есть в случае исходного списка (foo 1 2 (foo 5 (foo 100 1000))), заменяемого элемента foo и заданной последовательности из одного элемента "+" должны получить форму (foo 1 2 (foo 5 (foo 100 1000))).
A>>иными словами, если имя написанного макроса functional-replace должны наблюдать такую картину:
A>>A>>(macroexpand-1 '(functional-replace (foo 1 2 (foo 5 (foo 100 1000))) foo (+)))
A>>результат: (+ 1 2 (+ 5 (+ 100 1000)))
A>>соответственно форма (functional-replace (foo 1 2 (foo 5 (foo 100 1000))) foo (+))
A>>должна быть интерпретирована в результат 1108
A>>
Все никак руки не доходили отписаться здесь.
На самом деле — никакой не этюд, надо мне было учить матчасть.
Вариантов решений — куча.
В лоб, тупо и быстро — subst (тупо, потому что меняет все вхождения).
В случае использования другой функции (и/или применить измененный порядок аргументов) хватит за глаза формы с macroexpand (или flet, в зависимости от контекста задачи):
(macroexpand ((foo (&rest args) `(boo ,context ,@args) {source-form})
Lisp —