Macros 如何编写一个scheme宏来定义一个变量,并以字符串的形式获取该变量的名称?

Macros 如何编写一个scheme宏来定义一个变量,并以字符串的形式获取该变量的名称?,macros,scheme,Macros,Scheme,这主要是一个后续行动。我决定只记住YAGNI,并创建了一个全局变量(libpython)。我最初将其设置为#f,然后设置为。我添加了一个函数,用于检查该值是否已初始化: (define (get-cpyfunc name type) (lambda args (if libpython (apply (get-ffi-obj name libpython type) args) (error "Call init before using

这主要是一个后续行动。我决定只记住YAGNI,并创建了一个全局变量(
libpython
)。我最初将其设置为
#f
,然后设置为
init
时,code>。我添加了一个函数,用于检查该值是否已初始化:

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

我一直在阅读宏文档,试图弄明白这一点,但我似乎无法找到一种方法使其工作。有人能帮我吗(或者至少让我大致了解一下宏的样子)?或者,有没有一种方法可以在没有宏的情况下执行此操作?

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

(define Py_Initialize (get-cpyfunc 'Py_Initialize (_fun -> _void)))
然后让
获取cpyfunc
运行
(符号->字符串名)


诚然,可能有一种方法可以用
语法case
实现这一点(尽管我永远记不起它的语法),而且如果您使用的是CL-esque
define macro

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


我在另一个问题中回答了这个问题的大部分(我没有看到这个)。使用像这样提取绑定的函数是可以的,但这里可能存在的一个问题是,由于您仅在调用结果函数时生成绑定,因此每次调用时都会重新创建此绑定。快速解决此问题的简单方法是使用承诺,类似以下内容:

(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
    的集合。这是一个具有各种样式的绑定示例集合。创建绑定的宏在这些示例中非常常见


我想这是一种方法。我没有想到。我记不太清楚
语法大小写
符号字符串是在宏展开时运行还是在运行时运行?不在这里,因为
symbol->string
是生成代码的一部分(在模板内)。感谢您指出这些示例!我只是想有更多使用
ffi
的示例。
(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)))