Как работает `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)))