У меня есть LISP, написанный на JavaScript (https://jcubic.github.io/lips/ с онлайн-демонстрацией, где вы можете попробовать его), и у меня есть макрос, подобный этому:
(define-macro (globalize symbol)
(let ((obj (--> (. lips 'env) (get symbol))))
`(begin
,@(map (lambda (key)
(print (concat key " " (function? (. obj key))))
(if (function? (. obj key))
(let* ((fname (gensym))
(args (gensym))
(code `(define (,(string->symbol key) . ,args)
(apply (. ,obj ,key) ,args))))
(print code)
code)))
;; native Object.key function call on input object
(array->list (--> Object (keys obj)))))))
В этом коде я использую это:
(let ((obj (--> (. lips 'env) (get symbol))))
и я вызываю этот макрос, используя:
(globalize pfs)
для создания функции для каждого статического метода pfs (который представляет собой LightingFS из isomorphic-git, где каждая функция возвращает обещание, это как fsиз узла).
Но это не сработает для чего-то подобного:
(let ((x pfs))
(globalize x))
, потому что lips.env является глобальной средой.
Так что мой вопрос в том, как макросдолжно сработать?Должны ли они обрабатывать входные данные только как символы, чтобы они никогда не имели доступа к объекту до оценки кода lisp?
Как должен выглядеть макрос LISP, генерирующий набор функций на основе переменных.Например, в схеме, если у меня есть alist в переменной и я хочу сгенерировать функцию для каждой клавиши, которая будет возвращать значение:
input:
(define input `((foo . 10) (bar . 20)))
output:
(begin
(define (foo) 10)
(define (bar) 20))
Могу ли я написать макрос, который выдаст такой вывод, если я использую (macro input)
?Или единственный вариант - (macro ((foo . 10) (bar . 20)))
?
Я могу принять общий ответ Scheme или Common LISP, но, пожалуйста, не публикуйте макросы определения синтаксиса и гигиенические макросы из схемы, у моего lisp их нет и никогда не будет.
Проблема, кажется, в том, что я хочу получить доступ к значению во время раскрытия макроса, и оно должно иметь значение, которое во время выполнения.И второй вопрос eval в этом случае единственный вариант?
Это работает в biwascheme :
(define-macro (macro obj)
(let ((obj (eval obj)))
`(begin
,@(map (lambda (pair)
(let ((name (car pair))
(value (cdr pair)))
`(define (,name) ,value)))
obj))))
(define input `((foo . 10) (bar . 20)))
(macro input)
(foo)
;; ==> 10
(bar)
;; ==> 20
(в моем lisp eval donне работает как в biwascheme, но это другая проблема).
но это не работает, потому что x не глобален:
(let ((x '((g . 10)))) (macro x))
Является ли макрос с eval тем, что вы обычно делаете,или их следует избегать?Есть ли другой способ генерировать набор функций на основе объекта времени выполнения.