Для некоторого кода, с которым я работал, мне нужно было обработать 'x внутри макроса. Каков стандартный способ обработки этих значений?
У меня есть такой код:
(define (quoted-symbol? x)
(and (pair? x) (eq? (car x) 'quote) (symbol? (cadr x)) (null? (cddr x))))
(define-macro (test x)
(if (quoted-symbol? x)
`(begin
(display ',(cadr x))
(newline))))
(test 'hello) ;; 'hello will be expanded into list (quote hello)
Это то, как это должно быть обработано, или просто в макросе вы не используете символы в кавычках ?
ПРИМЕЧАНИЕ : я не спрашиваю о гигиенических c макросах (я спрашиваю о реальных макросах lisp), поэтому, пожалуйста, не отвечайте с помощью гигиенических c макросов.
РЕДАКТИРОВАТЬ :
Мой макрос работает правильно в Guile и BiwaScheme и в моей собственной схеме, как lisp в JavaScript. Вот лучший пример:
(define-macro (test x)
(if (quoted-symbol? x)
`',(cadr x)))
(define (example arg)
(list arg (test 'world)))
(example 'hello)
вопрос был не о display
, а о (cadr x)
.
EDIT2 : Вы задали этот вопрос здесь go, мой макрос:
(define-macro (--> expr . code)
"Helper macro that simplify calling methods on objects. It work with chaining
usage: (--> ($ \"body\")
(css \"color\" \"red\")
(on \"click\" (lambda () (print \"click\"))))
(--> document (querySelectorAll \"div\"))
(--> (fetch \"https://jcubic.pl\") (text) (match /<title>([^<]+)<\/title>/) 1)
(--> document (querySelectorAll \".cmd-prompt\") 0 \"innerText\")"
(let ((obj (gensym)))
`(let* ((,obj ,(if (and (symbol? expr) (not (null? (match /\./ (symbol->string expr)))))
`(.. ,expr)
`,expr)))
,@(map (lambda (code)
(let ((name (gensym))
(value (gensym)))
`(let* ((,name ,(cond ((quoted-symbol? code) (symbol->string (cadr code)))
((pair? code) (symbol->string (car code)))
(true code)))
(,value (. ,obj ,name)))
,(if (and (pair? code) (not (quoted-symbol? code)))
`(set! ,obj (,value ,@(cdr code)))
`(set! ,obj ,value)))))
code)
,obj)))
;; ---------------------------------------------------------------------------------------
(define (quoted-symbol? x)
"(quoted-symbol? code)
Helper function that test if value is quoted symbol. To be used in macros
that pass literal code that is transformed by parser.
usage:
(define-macro (test x)
(if (quoted-symbol? x)
`',(cadr x)))
(list 'hello (test 'world))"
(and (pair? x) (eq? (car x) 'quote) (symbol? (cadr x)) (null? (cddr x))))
макрос используется в моей схеме как lisp в JavaScript, например, строка do c предлагает:
(--> document (querySelectorAll ".class") 0 "innerText")
Я хочу для поддержки:
(--> document (querySelectorAll ".class") 0 'innerText)
Код можно протестировать в Интернете по адресу: https://jcubic.github.io/lips/ (код необходимо скопировать / вставить, поскольку в текущей версии разрешены только вызовы методов).
Чтобы получить расширение, вы можете использовать
(pprint (macroexpand (--> document (querySelector "x"))))
, если оно не работает (не расширяется), это означает, что макрос как-то не работает.
точка - это встроенная функция, которая получить свойство объекта и ..
макрос:
(define-macro (.. expr)
"(.. foo.bar.baz)
Macro that gets value from nested object where argument is comma separated symbol"
(if (not (symbol? expr))
expr
(let ((parts (split "." (symbol->string expr))))
(if (single parts)
expr
`(. ,(string->symbol (car parts)) ,@(cdr parts))))))
, которые можно использовать для получения вложенного свойства, например (.. document.body.innerHTML)