对于我正在工作的一些代码,我需要在宏中处理'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)
这是应该如何处理的,还是只是在宏中你不使用带引号的符号?
注意:我不是在问卫生宏(我问的是真正的 lisp 宏),所以请不要回答卫生宏。
编辑:
我的宏在 Guile 和 BiwaScheme 以及我自己的方案(如 JavaScript 中的 lisp)中正常工作。这是更好的例子:
(define-macro (test x)
(if (quoted-symbol? x)
`',(cadr x)))
(define (example arg)
(list arg (test 'world)))
(example 'hello)
问题不是关于display
,而是关于(cadr x)
。
EDIT2:你已经问过了,我的宏:
(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))))
该宏在我的方案中使用,如 JavaScript 中的 lisp,如文档字符串建议:
(--> document (querySelectorAll ".class") 0 "innerText")
我要支持:
(--> document (querySelectorAll ".class") 0 'innerText)
该代码可以在线测试:https ://jcubic.github.io/lips/ (您需要复制/粘贴代码,因为当前版本只允许方法调用)。
要获得扩展,您可以使用
(pprint (macroexpand (--> document (querySelector "x"))))
如果它不起作用(不要扩展),则意味着宏以某种方式损坏。
dot 是内置函数,可获取对象和..
宏的属性:
(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)