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

发布于 2024-09-03 12:00:14 字数 548 浏览 1 评论 0原文

这主要是

  (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 技术交流群。

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

发布评论

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

评论(3

仲春光 2024-09-10 12:00:14

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

(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 的集合。这是各种风格的装订示例的集合。创建绑定的宏在这些示例中非常常见。

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:

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

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.

江挽川 2024-09-10 12:00:14

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

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

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

诚然,可能有一种方法可以用 syntax-case 来做到这一点(尽管我永远记不起它的语法),而且如果你使用带有 CL 的Scheme,那肯定是这样。 esque 定义宏。

Why don't you change the generated code to

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

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-esque define-macro.

南巷近海 2024-09-10 12:00:14

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

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

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

> (define-syntax (my-syntax stx)
  (syntax-case stx ()
  [(_ id)
  #'(define-values (id) (values (symbol->string (quote id))))]))
> (my-syntax y)
> y
"y"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文