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

发布于 2024-09-28 13:27:22 字数 1648 浏览 2 评论 0原文

因此,我正在使用一个简单的文档字符串系统作为方案的热身,其想法是您可以执行以下操作:

(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)))))))

获取定义,移动参数/描述/return 调用包含在 begin 语句中的顶层并重建函数体,这样文档字符串调用仅在加载文件时执行一次,而不是每次调用函数时执行一次。我知道我可以手动将文档字符串内容放在顶层,但我正在尝试模拟 Python 文档字符串。

无论如何,我需要做的最后一个想法是将函数名称(上面的 foo )绑定到文档字符串调用中,以便 (param 'a“第一个参数”) 变为 (param 'foo 'a“第一个参数”)以便知道每个调用关联的函数。这就是我遇到麻烦的地方,我所做的每一次尝试都未能达到我想要的效果。

So I'm playing around with a simple doc-string system as a warmup in scheme, the idea being you could do something like:

(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)

Which would be turned into:

(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))))

The macro I've written:

(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)))))))

Takes the definition, moves the param/desc/return calls into the top level wrapped in begin statements and reconstructs the body of the function, that way the doc string calls are only executed once when the file is loaded rather than each time the function is called. I know I could manually put the doc-string stuff at the top level but I'm trying to emulate Python doc-strings.

Anyhow, the last think that I need to do is bind the function name (foo in above) into the doc-string calls, so that (param 'a "First parameter") becomes (param 'foo 'a "First parameter") so that the function each call is associated with is known. This is where I'm having trouble, every attempt I've made has failed to do what I want.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凉墨 2024-10-05 13:27:22

我建议使用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))]))

请原谅我的术语,因为我从未使用过文档字符串。
基本上,这与遵循函数 + params def、0 个或多个带有属性的标签以及代码语句的模式的任何内容相匹配。

然后,它只是重新安排一切。

I would suggest using define-syntax as it is hygienic and its syntax-rules are pretty easy to understand. syntax-rules are in a pattern-to-result format; if you can understand cond, you can understand syntax-rules.

I think this does what you want, judging by the before and after snippets.

(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))]))

Forgive my terminology because I've never used doc-strings.
Basically, this matches against anything that follows that pattern of a function + params def, 0 or more tags with attributes, and a code statement.

Then, it just rearranges everything.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文