Проверьте запуском
LISPEX
(call-with-values (lambda () (values 3 4)) (lambda (a b) (+ (* a a) (* b b))))Наблюдаемый результат
OUTPUT
25Разберите приём
- Получите пакет. Первая lambda возвращает два значения,
3и4, а не строит список. - Согласуйте потребителя. У второй lambda два параметра, поэтому её арность точно совпадает с пакетом.
- Вычисляйте обычно. Внутри потребителя
aиb— обычные одиночные значения, а арифметика возвращает25.
Как рассуждать
- Помещайте producer в специальный producer context, а не в операнд вызова, тест, инициализатор или RHS присваивания.
- Consumer получает каждое произведённое значение отдельным аргументом и обычно проверяется на арность.
- Используйте
(values)осознанно для нуля значений в допускающих отбрасывание путях.
Проверьте себя
Замените потребителя на list. Какой результат сохранится и чем он отличается от пакета производителя?
Ответ
Получится обычный список (3 4). call-with-values передал два аргумента, а list намеренно построил одно хранимое значение.
Частая ошибка
Не кодируйте семантические multiple values обычным списком, если вызывающий ожидает арность значений.
Куда дальше
Все контексты значений определены в руководстве, а ошибка несовпадающей арности — в главе о процедурах.