Callable-объекты
В некоторых языках программирования есть интересная возможность, позволяющая использовать объекты в качестве функций. В Common Lisp есть полноценные замыкания, так что такая возможность вроде бы не очень то и нужна, но, тем не менее, она также есть. Мне вряд ли удастся придумать пример, где она выглядела бы намного более выигрышною, чем замыкания, но я все же считаю её достаточно интересной.
Ниже простой пример классического "генератора чисел Фибоначчи"
(asdf:operate 'asdf:load-op 'alexandria)
(defpackage #:test
(:use #:closer-common-lisp))
(in-package #:test)
(defclass fibonacci-generator ()
((a :initform nil)
(b :initform nil))
(:metaclass funcallable-standard-class))
(defun next-fibonacci-number (generator)
(with-slots (a b) generator
(cond
((null a) (setf a 0))
((null b) (setf b 1))
(t (psetf a b
b (+ a b))
b))))
(defmethod shared-initialize :after ((fib fibonacci-generator) slot-names &key)
(set-funcallable-instance-function
fib
(lambda () (next-fibonacci-number fib))))
Здесь видно, что при определении класса fibonacci-generator используется метакласс funcallable-standard-class, а при инициализации объекта происходит вызов set-funcallable-instance-function - вот собственно и всё, что необходимо для создания подобных объектов.
Использовать fibonacci-generator можно, например, так:
repeat 20
collect (funcall fib))
(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)
Более подробную информацию о предмете обсуждения смотрите здесь .