Песочница

Создание и потребление нескольких значений

Используйте values, чтобы вернуть пакет значений, и call-with-values, чтобы передать этот пакет потребителю с подходящей арностью.

Проверьте запуском

LISPEX
(call-with-values (lambda () (values 3 4)) (lambda (a b) (+ (* a a) (* b b))))

Наблюдаемый результат

OUTPUT
25

Разберите приём

  1. Получите пакет. Первая лямбда возвращает два значения, 3 и 4, а не строит список.
  2. Согласуйте потребителя. У второй лямбды два параметра, поэтому её арность точно совпадает с пакетом.
  3. Вычисляйте обычно. Внутри потребителя a и b являются обычными одиночными значениями, а арифметика возвращает 25.

Как рассуждать

  • Помещайте производителя в отведённый для него контекст, а не в операнд вызова, тест, инициализатор связывания или правую часть присваивания.
  • Потребитель получает каждое произведённое значение отдельным аргументом и проходит обычную проверку арности.
  • Используйте (values) осознанно при возврате нуля значений в путях управления, допускающих отбрасывание.

Проверьте себя

Замените потребителя на list. Какой результат сохранится и чем он отличается от пакета производителя?

Ответ

Получится обычный список (3 4). call-with-values передал два аргумента, а list намеренно построил одно хранимое значение.

Частая ошибка

Не кодируйте несколько значений обычным списком, если вызывающий ожидает именно арность значений.

Куда дальше

Все контексты значений определены в руководстве, а ошибку несовпадающей арности объясняет глава о процедурах.

Контексты нескольких значений · Процедуры и арность