3.3 Using type-specific operations
declare
.
(defun list-add (l) (let ((sum 0)) (dolist (i l sum) (setq sum (+ i sum)))))
list-add
, you should declare both the argument types and the result types of the expression. In the following code, thedeclare
special form is used to declare the variablesi
andsum
to be of typefixnum
:
(defun list-add (l) (let ((sum 0)) (declare (fixnum sum)) (dolist (i l sum) (declare (fixnum i)) (setq sum (+ i sum)))))
(+isum)
is also implicitly declared to be of typefixnum
because the value of the expression is assigned to sum, which has been declared to be of typefixnum
. The Compiler is thus free to depend on these types and will use the fixnum-specific version of+
.
the
. It has the following form:(the value-type form)
the
to declare both the value type of the expression and the types of the list elements as they are retrieved:
(defun labels-list-add (l) (labels ((help-add (sum restl) ; Define a recursive helper ; function. (declare (fixnum sum)) (if (null restl) sum (help-add (the fixnum (+ sum (the fixnum (first restl)))) (rest restl))))) (help-add 0 l)))
+
.
ftype
orrestrictive-ftype
declarations.ftype
declarations to restrict arithmetic operators only in certain contexts. In many cases the result of applying arithmetic operators to fixnum values is not a fixnum unless the fixnum values are small. The expression (1+most-positive-fixnum
) does not produce a fixnum value, for example. If the fixnum values are small enough, however, you can useftype
declarations to restrict arithmetic operators. For example, the following declarations inform the Compiler that whenever the arguments to the declared operators are fixnum integers the value types will also be fixnums. The Compiler can thus use the fixnum forms of the operators:
(declare (ftype (function (&rest fixnum) fixnum) + -) (ftype (function (fixnum) fixnum) 1+ 1-))
list-add
that uses a singletype-reduce
declaration to restrict all numerical quantities within the function:
(defun fixnum-list-add (l) (declare (type-reduce number fixnum)) (let ((sum 0)) (dolist (i l sum) (setq sum (+ i sum)))))You can use type declarations to write fixnum-specific versions for generic routines. You must use caution, however, when defining fixnum-specific operators. Expressions that apply arithmetic operators to more than two arguments might not produce optimal compiled code. For example, the following expression cannot be fully optimized:
(the fixnum (+ (the fixnum x) (the fixnum y) (the fixnum z))))Although each of the arguments and the result of the entire expression are declared as fixnums, the Compiler cannot assume that the intermediate results will also be fixnums.
The following macro defines a fixnum-specific addition operator. Note that it automatically expresses the sum in terms of binary operators and adds the necessary declarations:
(defmacro fixnum-plus (&rest args) (case (length args) (0 '0) (1 (first args)) (2 '(the fixnum (+ (the fixnum ,(first args)) (the fixnum ,(second args))))) (t '(the fixnum (+ (the fixnum ,(first args)) (fixnum-plus ,@(rest args)))))))When this code is compiled, calls to fixnum-plus are coded directly into hardware add instructions.
Generated with Harlequin WebMaker