如何编写定义变量的方案宏,并将该变量的名称作为字符串?

时间:2010-05-28 15:04:32

标签: macros scheme

这主要是this question的后续行动。我决定只记住YAGNI并创建一个全局变量(libpython)。我最初将其设置为#f,然后在调用set!时将其设置为init。我添加了一个函数来处理是否已经初始化该值:

  (define (get-cpyfunc name type)
    (lambda args
      (if libpython
        (apply (get-ffi-obj name libpython type) args)
        (error "Call init before using any Python C functions"))))

所以现在这就是我想做的事情。我想定义一个宏,它将采取以下内容:

(define-cpyfunc Py_Initialize (_fun -> _void))

并将其转换为:

(define Py_Initialize (get-cpyfunc "Py_Initialize" (_fun -> _void)))

我一直在阅读宏文档来尝试解决这个问题,但我似乎无法找到一种方法来使其工作。任何人都可以帮我这个(或者至少让我对宏的外观有一个大概的了解)?或者有没有办法在没有宏的情况下做到这一点?

3 个答案:

答案 0 :(得分:1)

为什么不将生成的代码更改为

(define Py_Initialize (get-cpyfunc 'Py_Initialize (_fun -> _void)))

然后让get-cpyfunc运行(symbol->string name)

当然,可能有一种方法可以使用syntax-case(我永远不会记住语法),并且肯定如果你使用带有CL-esque的Scheme { {1}}。

答案 1 :(得分:1)

我在另一个问题中回答了大部分问题(我没有看到这个问题)。使用像这样拉出绑定的函数是很好的,但是这里可能存在的一个问题是,因为只有在调用结果函数时才生成绑定,所以在每次调用时都会重新创建此绑定。快速解决这个问题的一个简单方法是使用promises,如下所示:

(require scheme/promise)
(define (get-cpyfunc name type)
  (define the-function
    (delay (if libpython
             (get-ffi-obj name libpython type)
             (error "Call init before using any Python C functions"))))
  (lambda args (apply (force the-function) args)))

但这与我在上一个问题中发布的代码基本相同。

更多随机记录:

  • get-ffi-obj会接受一个符号作为要绑定的名称 - 这是有意的,可以使这些宏(如上一个问题)容易。

  • 在宏中使用(symbol->string 'name)很好。正如我在回复Nathan评论的评论中所提到的,这意味着它会在运行时被调用,但是mzscheme应该能够优化它,所以没有必要尝试编写一些在编译时完成工作的复杂宏。

  • 查看PLT目录 - 你会发现一个名为ffi的集合。这是具有各种样式的绑定示例的集合。在这些示例中,创建绑定的宏非常常见。

答案 2 :(得分:0)

这不是完整的答案,但我提出了一个满足这两个要求的宏(定义变量和带有该变量名称的字符串):

> (define-syntax (my-syntax stx)
  (syntax-case stx ()
  [(_ id)
  #'(define-values (id) (values (symbol->string (quote id))))]))
> (my-syntax y)
> y
"y"