Ответ 1
Несколько значений в CL
Язык Общий lisp описан в стандарте ANSI INCITS 226-1994 (R2004) и имеет множество реализаций. Каждый может реализовать несколько значений по своему усмотрению, и им разрешено, конечно же, забирать список для них (фактически, уровень совместимости Emacs Lisp для CL делает именно это - но это, решительно и намеренно, не общая реализация Lisp).
Цель
Однако цель этого средства - разрешить передачу (по крайней мере некоторых) нескольких значений без необходимости (т.е. без выделения кучи памяти) и всех реализаций CL я Знайте об этом. В этом смысле функция множественных значений является оптимизацией.
Конечно, реализация этой функции может быть очень различной для разных платформ и сценариев. Например, первые несколько (скажем, 20 - требуемые стандартом) хранятся в статике потока-локального вектора, следующие несколько ( 1000?) Выделяются в стеке, а остальные (если необходимо) выделяются в куче как вектор или список.
Использование
Например, функция floor
возвращает два значения.
Если вы пишете
(setq a (floor 10 3))
вы снимаете только первый и отбрасываете второй, вам нужно написать
(setf (values q r) (floor 10 3))
чтобы зафиксировать оба значения. Это похоже на то, что другие языки могут выражаться как
q,r = floor(10,3)
используя tuples, за исключением того, что CL не выделяет память для передачи (всего несколько) нескольких значений, а другие языки часто делают.
IOW, можно думать о нескольких значениях как эфемерной структуре.
Обратите внимание, что CL может преобразовывать несколько значений в списки:
(destructuring-bind (q r) (multiple-value-list (floor 10 3))
; use q & r here
...)
вместо более эффективного и сжатого
(multiple-value-bind (q r) (floor 10 3)
; use q & r here
...)
MV и тип
CL не имеет специальный тип для "объекта с несколькими значениями" именно потому, что он не выделяет отдельный объект для передачи нескольких значений. В этом смысле можно утверждать, что values
является синтаксическим сахаром.
Однако в CL можно объявить тип функции, возвращающий несколько значений:
(declaim (ftype (real &optional real) (values real real)) floor)
Это означает, что floor
возвращает два значения: real
(в отличие от возврата значения типа (values real real)
), т.е. в этом случае можно требовать злоупотребления обозначениями.
Ваш случай
В вашем конкретном случае type-of
является обычной функцией (т.е. не макросом или специальным оператором).
Вы передаете ему один объект, 1, потому что, если вы не используете multiple-value-bind
и друзей, используется только первое значение, поэтому
(type-of (values 1 2 3))
совпадает с
(type-of 1)
а тип 1 - bit
.
PS: Контрольные значения возврата
Одно использование values
для
управляйте возвращаемыми значениями функции.
Обычно возвращаемые значения функции CL относятся к значениям последней формы.
Иногда это нежелательно, например, последняя форма возвращает несколько
значения и вы хотите, чтобы ваша функция возвращала одно значение (или нет, например void
в C
):
(defun 2values (x y)
(floor y x))
(defun 1value (x y)
(values (floor y x)))
(defun no-values (x)
(print x)
(values))