所以我在玩一个简单的文档字符串系统作为方案的预热,你可以做如下的事情:
(def-with-doc (foo a b)
(desc "Takes two parameters and sums them")
(param 'a "First parameter")
(param 'b "Second parameter")
(return "Sum of arguments")
(+ a b)
会变成:
(begin
(begin
(desc 'foo "Takes two parameters and sums them")
(param 'foo 'a "First parameter")
(param 'foo 'b "Second parameter")
(return 'foo "Sum of arguments"))
(begin
(define (foo a b)
(+ a b))))
我写的宏:
(define doc-symbol-list '(param desc return))
(define-macro (def-with-doc arg-list #!rest body)
;; Loop over body, splitting into doc calls and everything else
(let loop ((remaining body) (docs '()) (main '()))
(if (null? remaining)
; Reverse accumulation order of docs and main
; And build re-ordered begin tree
(let ((docs (cons 'begin (reverse docs)))
(main (cons 'begin (reverse main))))
(cons 'begin `(,docs ,`(define ,arg-list ,main))))
; Accumulate into docs list if expression is reserved
; Otherwise into the body list
(let ((sexp (car remaining)) (rest (cdr remaining)))
(if (member (car sexp) doc-symbol-list)
(loop rest (cons sexp docs) main)
(loop rest docs (cons sexp main)))))))
获取定义,将param/desc/return调用移动到begin语句包装的顶层,并重新构造函数体,这样,在加载文件时,文档字符串调用只执行一次,而不是每次调用函数时。我知道我可以手动将Doc字符串放到顶层,但我正在尝试模拟python-Doc字符串。
总之,我最后一个需要做的是将函数名(上面的foo)绑定到Doc字符串调用中,这样(param'a“first parameter”)就变成(param'foo'a“first parameter”),这样每个调用所关联的函数都是已知的。这就是我遇到麻烦的地方,我所做的每一次尝试都没有达到我想要的效果。