• Lisp CLOS А вот скажите, можно ли как-нибудь помочь generic functions диспетчиться в рантайме, если знаю, к какому классу принадлежит значение, которое туда передается? И окажет ли это влияние на скорость диспетчинга? Кто-нибудь замерял этот вопрос вообще?

Replies (22)

  • @Crazy-Owl, вопрос о какой-то конкретной реализации, или ваабще?
  • @Sectoid, sbcl, он вроде активнее всего declare'ом пользуется
  • @Crazy-Owl, но если есть общее средство, было бы интересно послушать
  • @Crazy-Owl, ТОЛЬКО СТАТИЧЕСКАЯ ТИПИЗАЦИЯ! ТОЛЬКО КОМПАЙЛ-ТАЙМ-ПОЛИМОРФИЗМ! HASKELL OCAML УЛЬТРАХАРДКОР!
  • @L29Ah-banned, брызжет слюной, кидается предметами со стола
  • @Crazy-Owl, не, тольк из разряда теоритических. мысли в сторону WPO и т.п.
  • @L29Ah-banned, если убавить феерии и категоричности, пожалуй даже подпишусь)
  • @Crazy-Owl,
    Такая вот test suite. Скорее всего что-то не так сделал, потому что результат получился одинаковый.

    (defclass foo () ((bar :initarg :bar :accessor bar)))

    (defgeneric get-bar-inc (f))

    (defmethod get-bar-inc ((f foo)) (incf (bar f)))

    (defparameter f (make-instance 'foo :bar 1500))

    (defun gen-var (f)
    (time (loop for i upto 1000000
    doing (get-bar-inc f))))

    (defun spec-var (f)
    (declare (foo f))
    (time (loop for i upto 1000000
    doing (get-bar-inc f))))


    Результат:

    * (gen-var f)

    Evaluation took:
    0.512 seconds of real time
    0.514804 seconds of total run time (0.514804 user, 0.000000 system)
    100.59% CPU
    852,195,110 processor cycles
    0 bytes consed

    NIL
    * (spec-var f)

    Evaluation took:
    0.651 seconds of real time
    0.655204 seconds of total run time (0.655204 user, 0.000000 system)
    100.61% CPU
    1,085,937,180 processor cycles
    0 bytes consed

    NIL

    С declare получилось даже дольше.
  • @Crazy-Owl, а сфига там declare должен был чего-либо ускорить?
  • @Crazy-Owl, но если есть общее средствоДа, напиши простую функцию, из generic-метода вызывай её и её же вызывай когда знаешь точный тип, всё просто.
  • @archimag, поясни, пожалуйста
  • @Crazy-Owl, а что нужно ещё пояснять?
  • @archimag, ну я вроде как объявляю, к какому классу принадлежит f, думал, что конпелятор подставит нужную имплементацию сразу и уберет диспетчинг в рантайме
  • @archimag, диспетчинг в рантайме в generic-методе все равно никуда не денется
  • @Crazy-Owl, это как он может такое сделать? Ведь есть :around, :before и :after, а может и другие варианты при использовании MOP. Комплиятор не может знать как это должно работать в момент генерации кода.
  • @Crazy-Owl, диспетчинг в рантайме в generic-методе все равно никуда не денетсяДа его просто не будет, если ты не будешь звать generic-метод. Зачем ты вызываешь generic, когда знаешь точный тип? Сделай отдельную обычную фукнцию специально для обработки данного типа
  • @archimag, теперь понял, о чем ты. Действительно, для одного конкретного класса так удобнее. А если вариантов некоторое ограниченное множество от "области определения" generic-функции, то, видимо, придется использовать как есть.
  • @archimag, и, кстати, разве нельзя отдиспатчить :around, :before и :after в compile-time, если доподлинно известен класс, который в них передастся? (речь о теоретической возможности, а не о том, делают ли так современные компиляторы лиспа)
  • @Crazy-Owl, Способ построения "эффективного метода" определяется метаклассом, который может быть изменён в run-time, со всеми вытекающими
  • @archimag, все, больше вопросов не имею (вроде)
  • @archimag, спасибо за информацию
  • @Crazy-Owl, CLOS/MOP круты по функционалу, но за это надо платить