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