Определить goto в схеме - PullRequest
2 голосов
/ 20 октября 2019

В качестве упражнения для изучения 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 и ракетке (r6rs) он просто печатает

0
done

Какая реализация верна?

1 Ответ

3 голосов
/ 20 октября 2019

Я думаю, что верхний уровень отличается в разных реализациях. Для 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Вы можете создать новый язык и переопределить верхний уровень (через #%module-begin), чтобы получить поведение Guile без каких-либо изменений в программе.

...