Scheme/"The Seasoned Schemer":关于"try"函数定义的语法问题
Scheme/"The Seasoned Schemer": Question about the syntax of the definition of "try" function
Felleisen 和 Friedman 在他们的书 "The Seasoned Schemer" 中介绍了 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
?或者可能会提出不同的问题:如果 a
中调用了 var
,try
定义的哪一部分确定 try
被计算为 b
?
编辑 1: 抱歉,letcc
的定义不完整。添加了缺失的第一行。
编辑2:下面的代码可以在Racket中运行
(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
语法规则是模式匹配。点表示一对的 car
和 cdr
就像 lambda
/ define
:
中的其余参数一样
(define (my-list . args)
args)
列表只是嵌套的对。例如。 (1 2 3)
只是显示 (1 . (2 . (3 . ())))
的奇特方式。
所以(this is random symbols in a list)
将通过try
匹配this
匹配(try var a . b)
,is
匹配var
,random
匹配a
,而 (symbols in a list)
匹配 b
.
当您在扩展中看到相同的内容时,这意味着代码应该在点之后拼接匹配项。例如,前面示例中的 (var . b)
变为 (is symbols in a list)
。它类似于 b ...
但对系统来说更便宜。
我不是 Scheme 宏语法复杂性方面的专家,但我认为 try
的等效定义是:
(define-syntax try
(syntax-rules ()
((try var a b ...)
(letcc success
(letcc var (success a)) b ...))))
我发现这肯定更容易阅读。
(try e <a> <b> <c>)
(任一版本,至少在 Racket 中)然后扩展为
(letcc success
(letcc e
(success <a>))
<b> <c>)))
那么,当 <a>
被评估时,e
是一个延续,returns 它的参数来自内部 letcc
形式,在那里它们被忽略.如果 e
被调用,那就是你最终的结果,然后 <b>
和 <c>
以正常方式进行评估(我只放了不止一件事,因为我可以,它处理整个 .
...
东西)。如果 e
不是 在计算 <a>
期间被调用,那么 success
是 被调用,并且它也是一个延续,然后 returns 从整个表格中评估 <a>
的结果。
至少我认为是这样。
下面是我用来测试我理解的东西的一大块 Racket。
(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))
让我们试试看会发生什么。我正在使用 mit-scheme。
文件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
。
第二步,打印脱糖语法:
(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 层,返回第 1 层延续序列中的 4
。
Felleisen 和 Friedman 在他们的书 "The Seasoned Schemer" 中介绍了 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
?或者可能会提出不同的问题:如果 a
中调用了 var
,try
定义的哪一部分确定 try
被计算为 b
?
编辑 1: 抱歉,letcc
的定义不完整。添加了缺失的第一行。
编辑2:下面的代码可以在Racket中运行
(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
语法规则是模式匹配。点表示一对的 car
和 cdr
就像 lambda
/ define
:
(define (my-list . args)
args)
列表只是嵌套的对。例如。 (1 2 3)
只是显示 (1 . (2 . (3 . ())))
的奇特方式。
所以(this is random symbols in a list)
将通过try
匹配this
匹配(try var a . b)
,is
匹配var
,random
匹配a
,而 (symbols in a list)
匹配 b
.
当您在扩展中看到相同的内容时,这意味着代码应该在点之后拼接匹配项。例如,前面示例中的 (var . b)
变为 (is symbols in a list)
。它类似于 b ...
但对系统来说更便宜。
我不是 Scheme 宏语法复杂性方面的专家,但我认为 try
的等效定义是:
(define-syntax try
(syntax-rules ()
((try var a b ...)
(letcc success
(letcc var (success a)) b ...))))
我发现这肯定更容易阅读。
(try e <a> <b> <c>)
(任一版本,至少在 Racket 中)然后扩展为
(letcc success
(letcc e
(success <a>))
<b> <c>)))
那么,当 <a>
被评估时,e
是一个延续,returns 它的参数来自内部 letcc
形式,在那里它们被忽略.如果 e
被调用,那就是你最终的结果,然后 <b>
和 <c>
以正常方式进行评估(我只放了不止一件事,因为我可以,它处理整个 .
...
东西)。如果 e
不是 在计算 <a>
期间被调用,那么 success
是 被调用,并且它也是一个延续,然后 returns 从整个表格中评估 <a>
的结果。
至少我认为是这样。
下面是我用来测试我理解的东西的一大块 Racket。
(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))
让我们试试看会发生什么。我正在使用 mit-scheme。
文件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
。
第二步,打印脱糖语法:
(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 层,返回第 1 层延续序列中的 4
。