Как работает `values` в Scheme?

Из стандарта R5RS:

Values might be defined as follows:
(define (values . things)
  (call-with-current-continuation
    (lambda (cont) (apply cont things))))

Моим первым толкованием этого было то, что выражение вроде (+ (values 1 2)) эквивалентно (apply + '(1 2)) и даст результат 3, Но, согласно моим тестам, эта интерпретация неверна. Вот моя интерпретация кода выше: values это функция, принимающая любое количество аргументов, объединенная в список things, Тогда текущее продолжение (место, где values используется) вызывается со списком things "Разделены".

Что мне не хватает? Пример выше (+ (values 1 2)) выдает ошибку или 1 в зависимости от того, какой переводчик я использовал.

2 ответа

Решение

Видите, когда вы печатаете

(+ (values 1 2))

продолжение звонка values на самом деле единственный аргумент +, Таким образом, он либо обрабатывается как 1 (первый элемент списка, первое значение, созданное процедурой), либо как ошибка. R5RS говорит по этому поводу:

За исключением продолжений, созданных процедурой вызова со значениями, все продолжения принимают ровно одно значение. Эффект от передачи значения или нескольких значений в продолжения, которые не были созданы с помощью call-with-values, не определен.

С другой стороны, call-with-values правильно связать элементы вашего списка с его consumer формальные аргументы аргумента:

Вызывает аргумент производителя без значений и продолжение, которое при передаче некоторых значений вызывает процедуру потребителя с этими значениями в качестве аргументов.

Чтобы понять, что это за определение values значит, вам нужно также понять определение call-with-current-continuation, который определяется в терминах. И полезно, документация для values упоминает call-with-values, как пример того, как использовать результат values,

Итак, вы могли бы использовать (values 1 2) в контексте вроде:

(call-with-values (lambda () (values 1 2))
                  (lambda (x y) (+ x y)))
Другие вопросы по тегам