绑定函数名称作为宏内部的参数

时间:2010-10-24 22:13:07

标签: scheme

所以我正在玩一个简单的文档字符串系统作为计划的热身,这个想法是你可以做的事情:

(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文档字符串。

无论如何,最后我认为我需要做的是将函数名称(上面的foo)绑定到doc-string调用中,这样(param'a“First parameter”)就变成了(param'foo'a“First参数“)使得每个调用所关联的函数是已知的。这是我遇到麻烦的地方,我所做的每一次尝试都没能做到我想要的。

1 个答案:

答案 0 :(得分:1)

我建议使用define-syntax,因为它是卫生的,syntax-rules非常容易理解。 syntax-rules采用模式到结果的格式;如果您能理解cond,则可以理解syntax-rules

我认为这可以做你想要的,从前后片段判断。

(define-syntax def-with-doc
    (syntax-rules ()
      ;; this pattern
      [(_ (func params ...)
          (tag attributes ...)
          ...
          code)
       ;; is converted into
       (begin
         (tag (quote func) attributes ...)
         ...
         (define (func params ...)
           code))]))

请原谅我的术语,因为我从未使用过doc字符串。 基本上,这匹配任何遵循函数模式+ params def,0或更多带属性的标签和代码语句的东西。

然后,它只是重新排列所有内容。