Scheme中函数的机制
这是Scheme中的一个奇怪的函数:
(define f (致电/抄送 (lambda (x) x) ) )
(((f 'f) f) 1 )
当在命令行中调用 f 时,显示的结果是 f 。 这个机制的解释是什么?...
谢谢!
Here it is a strange function in Scheme:
(define f
(call/cc
(lambda (x) x) ) )
(((f 'f) f) 1 )
When f is called in the command line, the result displayed is f .
What is the explanation of this mechanism ?..
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您刚刚偶然发现了“延续”,这可能是计划中最难理解的事情。
call/cc
是call-with-current-continuation
的缩写,该过程的作用是将单个参数函数作为自己的参数,并使用当前的“继续”。那么什么是延续呢?这是出了名的难以解释,你可能应该用谷歌搜索一下以获得比我更好的解释。但延续只是一个参数的函数,其主体代表某个值的某种“延续”。
就像,当我们有
(+ 2 (* 2 exp))
并且 exp 是一个随机表达式时,如果我们评估该表达式,就会有一个“继续”等待该结果,即评估继续的地方,例如,如果计算结果为 3,它将将该值插入到表达式(* 2 3)
中,并从那里继续下一个“继续”,或者继续计算的位置,即(+ 2 ...)
。在几乎所有编程语言的上下文中,继续计算值的位置与开始时的位置相同,尽管许多语言中的 return 语句是一个关键的反例,但继续的位置完全不同比 return 语句本身更重要的地方。
在Scheme中,您可以直接控制您的延续,您可以像在那里那样“捕获”它们。
f
所做的无非是评估当前的延续,毕竟,当使用当前的延续调用(lambda (x) x)
时,它只是评估它,整个函数体也是如此。正如我所说,延续本身就是函数,其主体可以被视为它们要捕获的延续,Scheme 的设计者曾著名地表明,延续只是 lambda 抽象。因此,在代码中,f 首先计算出它被调用的延续。然后,将此延续作为函数应用于
'f
(符号)。这意味着该符号被带回到该延续,在那里它被再次作为符号求值,以揭示它所绑定的函数,该函数再次以符号作为其参数被调用,最终显示。有点令人难以置信,如果您看过电影“入门”,也许这可以解释它:
http://thisdomainisirrelevant.net /1047
You've just stumbled upon 'continuations', possibly the hardest thing of Scheme to understand.
call/cc
is an abbreviation forcall-with-current-continuation
, what the procedure does is it takes a single argument function as its own argument, and calls it with the current 'continuation'.So what's a continuation? That's infamously hard to explain and you should probably google it to get a better explanation than mine. But a continuation is simply a function of one argument, whose body represents a certain 'continuation' of a value.
Like, when we have
(+ 2 (* 2 exp))
with exp being a random expression, if we evaluate that expression there is a 'continuation' waiting for that result, a place where evaluation continues, if it evaluates to 3 for instance, it inserts that value into the expression(* 2 3)
and goes on from there with the next 'continuation', or the place where evaluation continues, which is(+ 2 ...)
.In almost all contexts of programming languages, the place where computation continues with the value is the same place as it started, though the
return
statement in many languages is a key counterexample, the continuation is at a totally different place than the return statement itself.In Scheme, you have direct control over your continuations, you can 'capture' them like done there. What
f
does is nothing more than evaluate to the current continuation, after all, when(lambda (x) x)
is called with the current continuation, it just evaluates to it, so the entire function body does. As I said, continuations are functions themselves whose body can just be seen as the continuation they are to capture, which was famously shown by the designers of Scheme, that continuations are simply just lambda abstractions.So in the code f first evaluates to the continuation it was called in. Then this continuation as a function is applied to
'f
(a symbol). This means that that symbol is brought back to that continuation, where it is evaluated again as a symbol, to reveal the function it is bound to, which again is called with a symbol as its argument, which is finally displayed.Kind of mind boggling, if you've seen the film 'primer', maybe this explains it:
http://thisdomainisirrelevant.net/1047