如何编写一个方案宏来定义变量并以字符串形式获取该变量的名称?
这主要是
(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)))
我一直在阅读宏文档以尝试弄清楚这一点,但我似乎无法找到使其工作的方法。谁能帮我解决这个问题(或者至少让我大致了解宏的外观)?或者有没有办法不用宏来做到这一点?
This is mostly a follow-up to this question. I decided to just keep YAGNI in mind and created a global variable (libpython
). I set it to #f
initially, then set!
it when init
is called. I added a function that should handle checking if that value has been initialized:
(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"))))
So now here's what I want to do. I want to define a macro that will take the following:
(define-cpyfunc Py_Initialize (_fun -> _void))
And convert it into this:
(define Py_Initialize (get-cpyfunc "Py_Initialize" (_fun -> _void)))
I've been reading through the macro documentation to try figuring this out, but I can't seem to figure out a way to make it work. Can anyone help me with this (or at least give me a general idea of what the macro would look like)? Or is there a way to do this without macros?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我已经在另一篇文章中回答了这个问题的大部分内容(我没有看到这个)。使用像这样提取绑定的函数很好,但这里可能出现的一个问题是,由于仅在调用结果函数时才生成绑定,因此每次调用时都会重新创建此绑定。快速解决此问题的一个简单方法是使用承诺,如下所示:
但这本质上与我在上一个问题中发布的代码几乎相同。
更多随机注释:
get-ffi-obj
将接受一个符号作为要绑定的名称 - 这是有意的,以使此类宏(如上一个问题)变得容易。在宏中使用
(symbol->string 'name)
就可以了。正如我在上面对 Nathan 的评论的评论回复中指出的,这意味着它在运行时被调用,但 mzscheme 应该能够对其进行优化,因此无需尝试编写一些复杂的宏来在编译时完成这项工作。查看 PLT 目录——您会发现一个名为
ffi
的集合。这是各种风格的装订示例的集合。创建绑定的宏在这些示例中非常常见。I've answered most of this question in the other one (I didn't see this one). It's fine to use a function that pulls out the bindings like this, but one possible problem here is that since you generate the binding only when the resulting function is called, this binding is re-created on each and every call. An easy way to solve this quickly is using promises, something like this:
But this is essentially almost the same as the code I posted in your previous question.
More random notes:
get-ffi-obj
will accept a symbol as the name to bind to -- this is intentional, to make such macros (as in the last question) easy.Using
(symbol->string 'name)
in a macro is fine. As I noted above in my comment reply to Nathan's comment, this means that it gets called at runtime, but mzscheme should be able to optimize that anyway, so there's no need to try and write some sophisticated macro that does the job at compile time.Look inside the PLT directory -- you will find a collection called
ffi
. This is a collection of examples of bindings with various styles. Macros that create the bindings are very common in these examples.为什么不将生成的代码更改为
然后让
get-cpyfunc
运行(symbol->string name)
?诚然,可能有一种方法可以用
syntax-case
来做到这一点(尽管我永远记不起它的语法),而且如果你使用带有 CL 的Scheme,那肯定是这样。 esque 定义宏。Why don't you change the generated code to
and then have
get-cpyfunc
run(symbol->string name)
?Granted, there is probably a way to do this with
syntax-case
(I can never remember its syntax though), and definitely if you're using a Scheme with CL-esquedefine-macro
.这不是完整的答案,但我想出了一个满足这两个要求的宏(定义一个变量和一个带有该变量名称的字符串):
It's not the complete answer, but I came up with a macro that meets both requirements (defines a variable and a string with the name of that variable):