在他们的书“经验丰富的阴谋家”中,费莱森和弗里德曼介绍了try函数。根据http://community.schemewiki.org/?seasoned-schemer,这个函数可以定义为
(define-syntax try
(syntax-rules ()
((try var a . b)
(letcc success
(letcc var (success a)) . b))))其中letcc被定义为
(define-syntax letcc
(syntax-rules ()
((letcc var body ...)
(call-with-current-continuation
(lambda (var) body ... ))))) 现在,虽然我了解try做了什么以及如何使用它,但我很难遵循它的正式定义。letcc在行中的success和(letcc var (success a)) . b的应用中点的确切含义是什么?
(letcc success
(letcc var (success a)) . b)try的?或者可能被问到不同的问题:如果在try中调用var,那么在var的定义中哪一部分可以确定try被求值为b
编辑1:对不起,letcc的定义不完整。增加了缺失的第一行。
编辑2:下面的代码可以在球拍中运行。
(define-syntax letcc
(syntax-rules ()
((letcc var body ...)
(call-with-current-continuation
(lambda (var) body ... )))))
(define-syntax try
(syntax-rules ()
((try var a . b)
(letcc success
(letcc var (success a)) . b))))
(try var (+ 1 1) 4)
; output: 2
(try var (var '(2)) 4)
; output: 4发布于 2020-02-19 17:44:52
我不是Scheme宏语法复杂性方面的专家,但我认为try的一个等价定义是:
(define-syntax try
(syntax-rules ()
((try var a b ...)
(letcc success
(letcc var (success a)) b ...))))我觉得这很容易读懂。
(try e <a> <b> <c>) (任何一个版本,至少在球拍中)然后扩展到
(letcc success
(letcc e
(success <a>))
<b> <c>)))因此,当计算<a>时,e是一个延续,它从内部letcc表单返回参数,在那里它们被忽略。如果调用了e,那么就会以正常的方式对<b>和<c>进行评估(我只在那里放置了一个以上的东西,因为我可以,它处理整个. ... )。如果e在<a>的计算过程中没有被调用,那么success就会被调用,并且它也是一个延续,然后返回整个表单中计算<a>的结果。
至少我认为这就是发生的事。
下面是一块球拍,我用它来测试我理解的东西。
(module+ test
(require rackunit))
(define-syntax let/cc
(syntax-rules ()
((let/cc var body ...)
(call-with-current-continuation
(lambda (var) body ... )))))
(define-syntax try
(syntax-rules ()
((try var a b ...)
(let/cc success
(let/cc var (success a)) b ...))))
(module+ test
(check-eqv?
(try fail (+ 1 1) 4)
2)
(check-eqv?
(try fail (fail '(2)) 4)
4)
(check-eqv?
(try fail
(begin 1 (fail) (error "failed to fail"))
4 5 6)
6))发布于 2020-02-20 07:21:13
让我们试着看看会发生什么。我在用麻省理工学院的计划。
文件try.scm:
(define-syntax letcc
(syntax-rules ()
((letcc var body ...)
(call-with-current-continuation
(lambda (var) body ... )))))
(define-syntax try
(syntax-rules ()
((try var a . b)
(letcc success
(letcc var (success a)) . b))))
(try var (+ 1 1) 4)
(try var (var '(2)) 4)第一步:编译文件:
> (sf "try")这将生成try.bin。
第二步,打印desugared语法:
> (pp (unsyntax (fasload "try")))
;Loading "try.bin"... done
................
(call-with-current-continuation
(lambda (success)
(call-with-current-continuation
(lambda (var) (success (+ 1 1))))
4))
(call-with-current-continuation
(lambda (success)
(call-with-current-continuation
(lambda (var) (success (var '(2)))))
4)))现在,您将显式地看到执行的内容,从而看到结果。
在(try var (+ 1 1) 4)的情况下,您跳出2个嵌套的calcc,因为您使用值2调用success,而在(try var (var '(2)) 4)中,您跳出了1层,第一个连续序列中的4将被返回。
https://stackoverflow.com/questions/60301595
复制相似问题