方案中的控制评估(guiile)
这似乎是一个简单的问题;也许它是如此简单,以至于很难找到能够找到答案的搜索。在Scheme(具体来说,Guile 实现,如果这有什么区别)中,我如何评估已引用的内容?
这就是我正在尝试做的事情。
我基本上需要确保我定义的函数按特定顺序评估其参数,因为评估一个参数引起的副作用取决于评估其他参数的过程。但是,Scheme 表示参数可以按任何顺序求值,因此我想通过引用参数来手动强制执行,然后按需要的顺序手动求值。
看来“eval”应该做我想做的事,但它有两个问题:
- 不鼓励使用它,所以我觉得应该有更好的方法来完成我想做的事情。
- 在Scheme中,eval似乎需要第二个参数,即环境。这让我很困惑。我希望它在语句出现的同一环境中进行评估,那么为什么我需要第二个参数呢?这可能吗?我玩了一下 eval ,似乎有些实现需要不同的参数(例如 mit-scheme 甚至不知道(交互环境)是什么!!!)
我尝试了其他技巧,比如构建 lambda :
(list 'lambda '() '(car (b c)))
但似乎必须对其进行评估才能生成过程。 我也尝试过:
(list lambda '() '(car (b c)))
但这会返回一个“原始内置宏”,它也不起作用。
编辑: 看起来宏可以用于控制求值顺序: (defmacro test1 (ab) `(开始,b,a))
This seems like a simple question; perhaps it is so simple that it is difficult to find a search that will find the answer. In Scheme (specifically, the Guile implementation if that makes any difference) how do I evaluate something that has been quoted?
Here's what I'm trying to do.
I basically need to ensure that a function I define gets its arguments evaluated in a specific order, because side effects caused by evaluating one argument are depended on during the evaluation of other arguments. However, Scheme says arguments can be evaluated in any order, so I want to manually force it by quoting the arguments and then manually evaluating them in the order that is needed.
It appears that "eval" is supposed to do what I want, but it has two problems:
- Its use is discouraged, so I feel like there should be a better way to accomplish what I want to do here.
- In Scheme it appears that eval takes a second parameter which is the environment. This is confusing to me. I want it to eval in the same environment the statement appears in, so why I should need a second parameter? Is this even possible? I've played with eval a bit and it appears that some implementations requires different parameters (e.g. mit-scheme doesn't even know what (interaction-environment) is!!!)
I've tried other tricks, like building up a lambda:
(list 'lambda '() '(car (b c)))
but it appears that this would then have to be evaluated to generate a procedure.
I also tried:
(list lambda '() '(car (b c)))
but this returns a "primitive-builtin-macro" which doesn't work either.
Edit:
Looks like a macro will work for controlling order of evaluation:
(defmacro test1 (a b) `(begin ,b ,a))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
eval
对于仅仅改变参数求值顺序来说是完全错误的工具。创建一个宏:如果必须的话,或者使用
defmacro
。eval
is utterly the wrong tool for just changing the order of evaluation of arguments. Create a macro instead:Or use
defmacro
, if you must.如果您需要评估列表结构(带有代表Scheme程序文本的带引号符号的嵌套列表),那么您应该使用
eval
。方案要求传递一个环境作为第二个参数,即使它是当前环境:如果您只需要按特定顺序进行计算,则可以使用
begin
、let
,或者只是一个函数体。它们定义了一系列求值:编辑:如果您需要一个参数化的代码块,您可以在其中传递未求值的表达式,然后强制按某种特定顺序对其求值,那么您可以使用以下技术之一:
宏(正如您已经提到的,只是为了完整性):
<前><代码>> (defmacro test1 (ab) `(开始,b,a))
> (测试1 (显示2) (显示3)
32
延迟计算(Scheme 用于延迟计算的特殊语法):
<前><代码>> (定义(test1 ab)(开始(力b)(力a)))
> (测试1 (延迟(显示2)) (延迟(显示3)))
32
常规 lambda 抽象和应用
<前><代码>> (定义(test1 ab)(开始(b)(a)))
> (test1 (lambda () (显示 2)) (lambda () (显示 3)))
32
If you need to evaluate a list structure (nested lists with quoted symbols that represent a Scheme program text), then you should use
eval
. Scheme requires passing an environment as a second argument, even if it is the current environment:If you just need to do your calculations in a particular order, you can enforce the order of evaluation for side effects by using
begin
,let
, or just a function body. They define a sequence of evaluations:Edit: If you need to have a parametrized block of code where you can pass expressions unevaluated and then force their evaluation in some particular order, then you may use one of these techniques:
A macro (as you've mentioned already, just for completeness):
A delayed computation (Scheme's special syntax for lazy evaluation):
A regular lambda abstraction and application
通过传入 lambda 表达式,您走在正确的轨道上。如果你有
...那么你可以像这样调用它:
这将使用所有参数调用
f
(a
,b
,c
)以未评估的形式。在f
中,您拥有完全的权力来选择评估它们的顺序。唯一的区别是您必须显式调用(x)
、(y)
和(z)
,并在中捕获它们的值>define
或let
之类的语句。这可以让您确保副作用仅发生一次。这里根本不需要宏。顺便说一句,不用担心到处使用大量 lambda,它们非常便宜。
You were on the right track with passing in lambdas. If you have
... then you can call it like so:
This will call
f
with all arguments (a
,b
,c
) in an unevaluated form. Insidef
, you have complete power to choose the order you evaluate them. The only difference is that you have to explicitly call(x)
,(y)
and(z)
, and capture their values insidedefine
orlet
-like statements. This lets you ensure that the side effects happen only once.No need for macros here at all. Btw, don't worry about using lots of lambdas everywhere, they are very cheap.