方案:eval 函数的正确应用?
在工作中,我在尝试使用Scheme实现配置脚本时遇到了一个基本问题。为了避免发明人工且受限制的语言,脚本应包含实际代码。稍后将评估此代码。为了使配置按需要工作,它必须能够访问某些变量。这些变量只有在评估的背景下才知道。因此,必须在当前环境中评估配置脚本。这是我正在谈论的一个原始示例:
(let ((a #t))
(wr "a is ..."
(eval '(if a "true" "false"))))
运行此代码时,我总是收到一条错误消息,告诉我变量“a”未知。所以问题是:您知道如何评估当前环境中的冻结代码吗?
PS:我使用bigloo编译器。
/////////////////////////////////////////////////////////////////////////////////// 编辑: //////////////////////////////////////////////// //////
当使用 Chris 建议的方法时,我遇到了另一个有趣的问题,即 case 关键字的使用。以下两个示例都使用相同的 case 结构,应该会触发“yes!”的输出。线。不幸的是他们的行为不同。
平常->输出是“是!”正如预期的那样:
(define testit "test")
(case testit
(("test")
(begin (newline) (write "yes!") (newline)))
(else
(begin (newline) (write "no!") (newline)))))
随着 eval ->输出令人惊讶地是“否”:
(define env (null-environment 5))
(eval '(define testit "test") env)
(eval '(case testit
(("test")
(begin (newline) (write "yes!") (newline)))
(else
(begin (newline) (write "no!") (newline)))))
这有什么意义吗?
at work I encountered a basic problem when trying to implement a configuration script with Scheme. To avoid the need of inventing an artificial and restricted language the script should contain actual code. This code shall be evaluated later on. To make the configuration work as desired it has to have access to certain variables. These variables are only known in the context of the evaluation. Therefore the configuration script has to be evaluated in the current environment. Here is a primitive example of what I am talking about:
(let ((a #t))
(wr "a is ..."
(eval '(if a "true" "false"))))
When running this code I'd always get an error message telling me that the variable 'a' is unknown. So the question is: Do you know how to evaluate frozen code inside the current environment?
P.S.: I use the bigloo compiler.
/////////////////////////////////////////////
EDIT: //////////////////////////////////////////////////////
When using the approach suggested by Chris I came to another interesting problem, the usage of the case keyword. The following two examples both use the same case construction which should trigger the output of a "yes!" line. Unfortunately they behave differently.
Usual -> output is "yes!" as expected:
(define testit "test")
(case testit
(("test")
(begin (newline) (write "yes!") (newline)))
(else
(begin (newline) (write "no!") (newline)))))
With eval -> output is surprisingly "no":
(define env (null-environment 5))
(eval '(define testit "test") env)
(eval '(case testit
(("test")
(begin (newline) (write "yes!") (newline)))
(else
(begin (newline) (write "no!") (newline)))))
Does that make any sense?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
eval
无法访问词法变量,例如使用let
定义的变量。相反,您必须创建一个环境,并用您想要提供的变量填充它。例如:
eval
cannot access lexical variables, such as those defined usinglet
.Instead, you have to create an environment, and populate it with the variables you want to make available. For example:
为了回答您的编辑,您没有将 env 作为参数传递给最后一个 eval。如果未给出该参数,则 eval 创建的环境中不存在 testit。
这可能是一个错字,但如果不是,那就是你的问题了。
To answer your edit, you aren't passing env as an argument to the last eval. testit doesn't exist in the environment that eval creates if that argument isn't given.
That may be a typo, but if not, that's your problem.