在 scheme 中定义 goto
Define goto in scheme
作为学习 call/cc 和宏的练习,我尝试定义 goto。
(define-syntax label
(syntax-rules ()
((_ name)
(begin
(define name)
(call/cc (lambda (c) (set! name c)))))))
(define (goto label) (label))
(define i 0)
(label start)
(display i) (newline)
(set! i (+ i 1))
(if (< i 3) (goto start))
(display "done") (newline)
它在 guile-2.0 中有效,但在 chez scheme 和 racket (r6rs) 中它只打印
0
done
哪个实现是正确的?
我认为顶层在不同的实现中是不同的。对于 Racket,call/cc
捕获到单个最顶层表达式的延续,而不是整个程序。我认为 Guile 掌握了整个程序。因此差异。
您可以通过在函数中编写代码来获取 Guile 的行为:
#lang r5rs
(define-syntax label
(syntax-rules ()
((_ name)
(begin
(define name #f)
(call-with-current-continuation (lambda (c) (set! name c)))))))
(define (goto label) (label))
(define (main)
(define i 0)
(label start)
(display i) (newline)
(set! i (+ i 1))
(if (< i 3) (goto start) #f)
(display "done") (newline))
(main)
这输出:
0
1
2
done
请注意,如果您使用 Racket,您可以创建一种新语言并重新定义 toplevel(通过 #%module-begin
)以获得 Guile 的行为,而无需对程序进行任何修改。
作为学习 call/cc 和宏的练习,我尝试定义 goto。
(define-syntax label
(syntax-rules ()
((_ name)
(begin
(define name)
(call/cc (lambda (c) (set! name c)))))))
(define (goto label) (label))
(define i 0)
(label start)
(display i) (newline)
(set! i (+ i 1))
(if (< i 3) (goto start))
(display "done") (newline)
它在 guile-2.0 中有效,但在 chez scheme 和 racket (r6rs) 中它只打印
0
done
哪个实现是正确的?
我认为顶层在不同的实现中是不同的。对于 Racket,call/cc
捕获到单个最顶层表达式的延续,而不是整个程序。我认为 Guile 掌握了整个程序。因此差异。
您可以通过在函数中编写代码来获取 Guile 的行为:
#lang r5rs
(define-syntax label
(syntax-rules ()
((_ name)
(begin
(define name #f)
(call-with-current-continuation (lambda (c) (set! name c)))))))
(define (goto label) (label))
(define (main)
(define i 0)
(label start)
(display i) (newline)
(set! i (+ i 1))
(if (< i 3) (goto start) #f)
(display "done") (newline))
(main)
这输出:
0
1
2
done
请注意,如果您使用 Racket,您可以创建一种新语言并重新定义 toplevel(通过 #%module-begin
)以获得 Guile 的行为,而无需对程序进行任何修改。