答案 0 :(得分:8)
执行此功能:
(defun add (x y)
(+ x y))
进行一般加法。它支持整数,浮点数,复数和比率作为参数-Lisp中定义的所有数字类型。
但是,如果您有:
(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)
之类的浮点数或仅传递(add 3)
等浮点数来违反这一诺言,您就会遇到很大的麻烦-这可能会破坏数据结构,甚至退出Lisp。
第二个函数可以称为%add-2-fixnums
,以表明它是特殊的,不是专门用于一般用途,而是专门用于某些自变量,并且调用者必须非常小心。
答案 1 :(得分:4)
不带%
的函数是某些功能的常规接口,甚至可以检查其参数。然后,它调用了一个底层实现。
带有前缀%
的相同功能可能甚至可以以特定于平台的方式有效地实现该功能。
如果此函数然后使用宏进行更具体的低级代码生成,则可以在宏之前加上%%
。
其他情况也可以看到:
示例:如果例如检查Clozure Common Lisp的源代码,则%
命名约定有很多用途。