[lisp][etude] functional replacer macro
От: A13x США  
Дата: 22.10.09 14:30
Оценка:
После долгого медитирования над макросами родилась маленькая задачка.

Напишите макрос на 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
Re: [lisp][etude] functional replacer macro
От: VoidEx  
Дата: 22.10.09 20:52
Оценка:
Здравствуйте, A13x, Вы писали:

Свертка же. ЛИСПы не знаю, но думаю, должно быть достаточно тривиально.
Re: [lisp][etude] functional replacer macro
От: mryau Россия http://woodland.ru/~wjdogs
Дата: 24.10.09 14:36
Оценка: 1 (1)
Здравствуйте, 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>
Re[2]: [lisp][etude] functional replacer macro
От: Аноним  
Дата: 29.10.09 15:36
Оценка:
Здравствуйте, 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 —
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.