如何在 Racket 中提供函数列表?
How do I provide a list of functions in Racket?
如果我想在当前模块之外使用某个功能,我可以执行以下操作...
(provide my-function)
我可以为函数列表执行此操作吗?
我尝试了以下...
(define f1 ...) ; body omitted for clarity
(define f2 ...) ; ditto
(define my-funs '(f1 f2))
(provide my-funs)
...但是当我尝试时,它给出了“Unbound identifier in: f1”。
我可以这样做吗?谢谢
更新: 只是为了澄清我在这里想做什么,我正在学习 Beautiful Racket,并且正在做第一个教程。在他 defines the expander 的阶段,他添加了一个 handle
函数来处理运算符...
(define (handle [arg #f])
(cond
[(number? arg) (push-stack! arg)]
[(or (equal? * arg) (equal? + arg))
(define op-result (arg (pop-stack!) (pop-stack!)))
(push-stack! op-result)]))
但是,为了完成这项工作,他 provide
同时 +
和 *
...
(provide + *)
这意味着这两个运算符被硬编码了两次。添加对其他运算符的支持时,您需要修改 handle
函数和 provide
调用。我正在尝试确定我们是否可以定义一个运算符列表,并在两者中使用它,因此您只需进行一次修改即可支持新的运算符。
不,你不能这样做。
您可以使用 filtered-out
and begin-for-syntax
导出函数列表(如下所示),但这会阻止您在代码中使用该列表。
正在导出列表
#lang racket
(module fns racket
(require racket/provide)
(define (f1 a) (+ a 1))
(define (f2 a) (+ a 2))
(begin-for-syntax
(define my-funs '(f1 f2)))
(provide
(filtered-out
(λ (name) (and (member (string->symbol name) my-funs) name))
(all-defined-out))))
(require 'fns)
(display (f1 2))
这是如何运作的
provide
可以采用任意数量的 provide-spec
形式,指定多个 provide-spec
等同于编写多个 provide
形式。可用的 provide-spec
形式之一是 all-defined-out
,它将导出模块中所有已定义的符号(如果未明确指定模块,则导出文件)。
通过要求 racket/provide
,我们可以访问可以转换和操作 provide-spec
表单的辅助函数; filtered-out
尤其允许我们 运行 任意代码覆盖 provide-spec
和 return 一个有效的 provide-spec
。 (所需的 proc-expr
是一个函数,它接受一个字符串(导出标识符的字符串值)和 returns 一个字符串或一个假值。这就是为什么在使用 member
时,我们将它包装起来在 and
和 return 原始名称本身。这也可以通过 findf
完成: (λ (name) (findf (λ (n) (equal? (string->symbol name) n)) my-funs))
)
然而,这还不够,因为 provide
是在“编译时”执行的,这意味着我们的列表 my-funs
尚不可用。为了处理这个问题,我们需要将该定义包装在 begin-for-syntax
中,这使得绑定在“编译时”也可用。但是,通过将 my-funs
移动到“编译时”,您将失去在非“编译时”代码中使用 my-funs
的能力。这意味着,例如,您不能说 (cond ... [(member arg my-funs) ...])
:
(define (handle [arg #f])
(cond
[(number? arg) (push-stack! arg)]
[(member arg my-funs)
;; ^--- Error here with "my-funs: unbound identifier"
(define op-result (arg (pop-stack!) (pop-stack!)))
(push-stack! op-result)]))
如果我想在当前模块之外使用某个功能,我可以执行以下操作...
(provide my-function)
我可以为函数列表执行此操作吗?
我尝试了以下...
(define f1 ...) ; body omitted for clarity
(define f2 ...) ; ditto
(define my-funs '(f1 f2))
(provide my-funs)
...但是当我尝试时,它给出了“Unbound identifier in: f1”。
我可以这样做吗?谢谢
更新: 只是为了澄清我在这里想做什么,我正在学习 Beautiful Racket,并且正在做第一个教程。在他 defines the expander 的阶段,他添加了一个 handle
函数来处理运算符...
(define (handle [arg #f])
(cond
[(number? arg) (push-stack! arg)]
[(or (equal? * arg) (equal? + arg))
(define op-result (arg (pop-stack!) (pop-stack!)))
(push-stack! op-result)]))
但是,为了完成这项工作,他 provide
同时 +
和 *
...
(provide + *)
这意味着这两个运算符被硬编码了两次。添加对其他运算符的支持时,您需要修改 handle
函数和 provide
调用。我正在尝试确定我们是否可以定义一个运算符列表,并在两者中使用它,因此您只需进行一次修改即可支持新的运算符。
不,你不能这样做。
您可以使用 filtered-out
and begin-for-syntax
导出函数列表(如下所示),但这会阻止您在代码中使用该列表。
正在导出列表
#lang racket
(module fns racket
(require racket/provide)
(define (f1 a) (+ a 1))
(define (f2 a) (+ a 2))
(begin-for-syntax
(define my-funs '(f1 f2)))
(provide
(filtered-out
(λ (name) (and (member (string->symbol name) my-funs) name))
(all-defined-out))))
(require 'fns)
(display (f1 2))
这是如何运作的
provide
可以采用任意数量的 provide-spec
形式,指定多个 provide-spec
等同于编写多个 provide
形式。可用的 provide-spec
形式之一是 all-defined-out
,它将导出模块中所有已定义的符号(如果未明确指定模块,则导出文件)。
通过要求 racket/provide
,我们可以访问可以转换和操作 provide-spec
表单的辅助函数; filtered-out
尤其允许我们 运行 任意代码覆盖 provide-spec
和 return 一个有效的 provide-spec
。 (所需的 proc-expr
是一个函数,它接受一个字符串(导出标识符的字符串值)和 returns 一个字符串或一个假值。这就是为什么在使用 member
时,我们将它包装起来在 and
和 return 原始名称本身。这也可以通过 findf
完成: (λ (name) (findf (λ (n) (equal? (string->symbol name) n)) my-funs))
)
然而,这还不够,因为 provide
是在“编译时”执行的,这意味着我们的列表 my-funs
尚不可用。为了处理这个问题,我们需要将该定义包装在 begin-for-syntax
中,这使得绑定在“编译时”也可用。但是,通过将 my-funs
移动到“编译时”,您将失去在非“编译时”代码中使用 my-funs
的能力。这意味着,例如,您不能说 (cond ... [(member arg my-funs) ...])
:
(define (handle [arg #f])
(cond
[(number? arg) (push-stack! arg)]
[(member arg my-funs)
;; ^--- Error here with "my-funs: unbound identifier"
(define op-result (arg (pop-stack!) (pop-stack!)))
(push-stack! op-result)]))