Возьмите эту функцию:
(defun add (x y)
(+ x y))
, которая выполняет общее сложение.Он поддерживает целые числа, числа с плавающей точкой, комплексные числа и отношения в качестве аргументов - все числовые типы, определенные в Лиспе.
Однако, если у вас есть:
(defun add (x y)
(declare (fixnum x y) (optimize speed (safety 0) (debug 0)))
(the fixnum (+ x y)))
, это говорит компилятору оптимизировать функцию дляfixnum
значений, которые помещаются в регистр сборки.Когда вы используете реализацию, которая компилируется для сборки, это приводит к очень эффективному коду, как вы можете проверить с помощью (disassemble (compile 'add))
.Например, в Allegro CL:
cl-user(10): (disassemble 'add)
;; disassembly of #<Function add>
;; formals: x y
;; code start: #x10008ae4740:
0: 48 01 f7 addq rdi,rsi
3: f8 clc
4: 4c 8b 74 24 10 movq r14,[rsp+16]
9: c3 ret
Однако этот более быстрый код достигается за счет отсутствия любой проверки ошибок: код предполагает , который вы передаете в 2 fixnum
аргументов, не более или менее, а также вы обещаете, что результат не будет превышать диапазон fixnum
- например, не (add most-positive-fixnum most-positive-fixnum)
.
Если вы нарушите это обещание, передавая числа с плавающей запятой, такие как (add 3.4 1.2)
или только arg (add 3)
, о котором вы мечтаете - это может привести к повреждению структур данных или даже к выходу из Lisp.
Вторая функция может быть вызвана %add-2-fixnums
, чтобы указать, что она особенная, не предназначена для общего использования, новместо этого он специализируется на определенных аргументах, и вызывающие абоненты должны быть очень осторожны.