-
Notifications
You must be signed in to change notification settings - Fork 1
Tutorial 4: Composition
Mark Cox edited this page Sep 18, 2017
·
1 revision
The template function system is capable of automatically instantiating template functions that are dependencies of other template functions.
A keen reader of Tutorial 3: Optional and Rest Arguments would have noticed that the compute-mean function is not a template function.
We fix this in the example below to illustrate automatic instantiation.
The code below is the compute-mean template function.
(eval-when (:compile-toplevel :load-toplevel :execute)
(defun make-compute-mean-lambda-form (argument-specification)
(destructuring-argument-specification (<array>) argument-specification
`(lambda (array)
(declare (type ,<array> array))
(let* ((mean (coerce 0 (array-element-type array)))
(count (array-total-size array)))
(when (zerop count)
(error "Array length is zero."))
(dotimes (i count)
(incf mean (row-major-aref array i)))
(/ mean count)))))
(defun make-compute-mean-function-type (argument-specification)
`(function ,argument-specification number)))
(define-template compute-mean (array)
(:lambda-form-function #'make-compute-mean-lambda-form)
(:function-type-function #'make-compute-mean-function-type))We now define the nremove-mean template function.
(eval-when (:compile-toplevel :load-toplevel :execute)
(defun make-nremove-mean-lambda-form (argspec)
(destructuring-argument-specification (<array> &key ((:mean <mean>))) argspec
`(lambda (array &key mean)
(declare (type ,<array> array)
(type (or null ,<mean>) mean))
(let* ((mean (coerce (or mean (compute-mean (the ,<array> array)))
(array-element-type array))))
(dotimes (i (array-total-size array))
(decf (row-major-aref array i) mean)))
(values))))
(defun make-nremove-mean-function-type (argspec)
`(function ,argspec (values))))
(define-template nremove-mean (array &key mean)
(:lambda-form-function #'make-nremove-mean-lambda-form)
(:function-type-function #'make-nremove-mean-function-type))Note that the compute-mean template function is invoked inside the lambda form of nremove-mean.
We now instantiate specialisation of the remove nremove-mean template.
(require-instantiations (nremove-mean (array)
((simple-array double-float))
((simple-array single-float))))We can now use the meta-object protocol to see how many instantiations of the compute-mean template function there are.
(defun show-instantiations (template-function-name)
(format t "~&Instantiations for ~A:" template-function-name)
(loop
for instantiation in (instantiations (find-template-function template-function-name))
for index from 1
do
(format t "~&~d: ~A" index (instantiation-argument-specification instantiation)))
(terpri))
(show-instantiations 'compute-mean)
(show-instantiations 'nremove-mean)
;; Instantiations for compute-mean:
;; 1: (array)
;; 2: ((simple-array double-float))
;; 3: ((simple-array single-float))
;; Instantiations for nremove-mean:
;; 1: (array)
;; 2: ((simple-array double-float))
;; 3: ((simple-array single-float))