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