← Blog of oldlisper

Callable-объекты

· 18.05.2011 00:00
· original author: archimag

Callable-объекты

В некоторых языках программирования есть интересная возможность, позволяющая использовать объекты в качестве функций. В Common Lisp есть полноценные замыкания, так что такая возможность вроде бы не очень то и нужна, но, тем не менее, она также есть. Мне вряд ли удастся придумать пример, где она выглядела бы намного более выигрышною, чем замыкания, но я все же считаю её достаточно интересной.

Ниже простой пример классического "генератора чисел Фибоначчи"

(asdf:operate 'asdf:load-op 'closer-mop)
(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 можно, например, так:

TEST> (loop with fib = (make-instance '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)

Более подробную информацию о предмете обсуждения смотрите здесь .