1. Куча / Говнокод #16690

    +125

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    81. 81
    82. 82
    (closer-mop:defclass virtual-metaclass (closer-mop:standard-class) ())
    
    (closer-mop:defclass virtual-slot-definition
        (closer-mop:standard-slot-definition)
      ((function :initarg :function 
                 :accessor virtual-slot-definition-function)))
    
    (defmethod slot-definition-allocation ((slotd virtual-slot-definition))
      :virtual)
    
    (defmethod (setf slot-definition-allocation) 
        (allocation (slotd virtual-slot-definition))
      (unless (eq allocation :virtual)
        (error "Cannot change the allocation of a ~S"
               'virtual-direct-slot-definition)) allocation)
    
    (closer-mop:defclass virtual-direct-slot-definition 
        (closer-mop:standard-direct-slot-definition
         virtual-slot-definition) ())
    
    (defmethod closer-mop:direct-slot-definition-class
        ((class virtual-metaclass) &rest initargs)
      ;; Use virtual-direct-slot-definition if appropriate.
      (if (eq (getf initargs :allocation) :virtual)
          (find-class 'virtual-direct-slot-definition)
          (call-next-method)))
    
    (closer-mop:defclass virtual-effective-slot-definition 
        (closer-mop:standard-effective-slot-definition
         virtual-slot-definition) ())
    
    (defmethod closer-mop:effective-slot-definition-class 
        ((class virtual-metaclass) &rest initargs)
      ;; Use virtual-effective-slot-definition if appropriate.
      (let ((slot-initargs (getf initargs :initargs)))
        (if (member :virtual-slot slot-initargs)
            (find-class 'virtual-effective-slot-definition)
            (call-next-method))))
    
    (defmethod closer-mop:compute-effective-slot-definition 
        ((class virtual-metaclass) name direct-slot-definitions)
      ;; Copy the function into the effective slot definition
      ;; if appropriate.
      (let ((effective-slotd (call-next-method)))
        (dolist (slotd direct-slot-definitions)
          (when (typep slotd 'virtual-slot-definition)
            (setf (virtual-slot-definition-function effective-slotd) 
                  (virtual-slot-definition-function slotd))
            (return)))
        effective-slotd))
    
    (defmethod closer-mop:slot-value-using-class 
        ((class virtual-metaclass) object slot-name)
      (let ((slotd (find slot-name (closer-mop:class-slots class) 
                         :key 'closer-mop:slot-definition-name)))
        (if (typep slotd 'virtual-slot-definition)
            (funcall (cadr (virtual-slot-definition-function slotd)) :get object)
            (call-next-method))))
    
    (defmethod (setf closer-mop:slot-value-using-class) 
        (value (class virtual-metaclass) object slotd)
      (if (typep slotd 'virtual-slot-definition)
          ;; This is ugly and probably not portable, but what if?
          (funcall (cadr (virtual-slot-definition-function slotd))
                   :set object value)
          (call-next-method)))
    
    (defmethod closer-mop:slot-boundp-using-class 
        ((class virtual-metaclass) object slot-name)
      (let ((slotd (find slot-name (closer-mop:class-slots class) 
                         :key 'closer-mop:slot-definition-name)))
        (if (typep slotd 'virtual-slot-definition)
            (funcall (cadr (virtual-slot-definition-function slotd)) :is-set object)
            (call-next-method))))
    
    (defmethod closer-mop:slot-makunbound-using-class 
        ((class virtual-metaclass) object slot-name)
      (let ((slotd (find slot-name (closer-mop:class-slots class) 
                         :key 'closer-mop:slot-definition-name)))
        (if (typep slotd 'virtual-slot-definition)
            (funcall (virtual-slot-definition-function slotd) :unset object)
            (call-next-method))))

    О простоте объектно-ориентированого программирования, или страшная правда, которую от вас так долго скрывали.
    Написано по мотивам: http://www.lispworks.com/documentation/lw50/LWUG/html/lwuser-173.htm В попытке сделать это, по возможности, портабельным (на SBCL вроде даже завелось).

    Я понимаю, что читать это никто не будет, поэтому, краткий пересказ событий:
    Захотелось мне виртуальных свойств, ну тоесть так, чтобы при обращении к Сипипишной библиотеке, для которой я ваяю оберкту не было различий между обычными Лисповыми объектами и Сипипишными.
    Простой вариант - скопировать значения, но перформанс же!
    И вот родился этот вариант. (Использование не показано, т.как не влезло).

    Запостил: wvxvw, 12 Сентября 2014

    Комментарии (16) RSS

    • tl;dr: код говно.
      Ответить
    • > closer-mop

      closure mop?

      клиента "закрыли" - и остатки с пола шваброй собирают?
      Ответить
      • Если интересно почему такое название: clos - Common Lisp Object System, mop - Meta Object Protocol. closer-mop - это библиотека, которая "чистит" разные реализации ООП в разных Лиспах, приводя их более-менее к общему знаменателю. Но вот с парсингом опций у слотов оказалась проблема - эта библиотека не предлагает никакой платформонезависимой функции, которую бы гарантировано вызвали, чтобы обработать эти опции. Судя по тому, как мне пришлось это переделать для SBCL на Аллегро это не взлетит.
        Ответить
    • > обращении к Сипипишной библиотеке

      О, эти отважные люди, лезущие в плюсовый ABI. Кмк, то, что они делают - бессмысленная борьба с неизбежным обломом и построение замков на костылях. Как минимум до тех пор, пока Саттер не протолкнёт свой extern "abi".
      Ответить
      • Не, там за меня уже разработчки либы все сделали. Т.е. доступ не напрямую к С++ методам, а к Си оберктам, которые потом вызывают эти самые С++ методы.

        Они даже SWIG интерфейс написали, который оказался даже на 90% годным.
        Ответить
        • уау! SWIG для чего то все таки работает?

          пробовал много лет назад для перла пользоватся - что генерило не компилилось, а док кот наплакал.
          Ответить
          • Судя по всему, для Явы работает хорошо т.как ява обертками пользуются в другом проекте. Перловый модуль я скомпилировал, когда собирал С++ проект, но как работает - не знаю, т.как не пробовал. С документацией у SWIG вроде нормально сейчас. Я про него узнал всего пару месяцев назад, как оно раньше было не знаю, но друг, с которым я над этим проектом работаю был в примерно таком же состоянии - в том смысле, что он не думал, что оно заработает вообще.
            Ответить
          • > SWIG для чего то все таки работает?

            У нас точно используется, но не в моём проекте (нам boost.python хватает).
            Ответить
            • > boost.python
              Реквестирую boost.javascript!
              Ответить
              • А в Qt же что-то было жсоподобное...
                Ответить
                • Почему было? Есть. И интерфейс с крестами неплох, но очень сильно привязан к кутишной метаинфе.
                  Ответить
                • qtscript
                  Ответить
              • > Реквестирую boost.javascript!

                Ага, сначала нужно запилить boost.js_impl. У пистона хотя бы есть де-факто стандартная реализация со стабильным нативным интерфейсом. А у каждого жс свой апи.

                Вот boost.lua вполне реален, я даже удивлён, что такой штуки в бусте нет.
                Ответить
                • Ну это ж буст, могли бы обобщенное API сделать, которое от конкретной реализации js абстрагированно...

                  Основные мысли вроде бы на любом движке можно выразить:
                  - умный указатель, знающий о GC
                  - какой-нибудь вариантный тип
                  - проброс крестофункции в жс
                  - проброс крестообъекта в жс
                  - обращение к массивам/объектам из крестов
                  - вызов жсной функции из крестов
                  - интерфейс для отладки с бектрейсом и переменными

                  Вот вроде и всё, что нужно для счастья.
                  Ответить
    • Слегка оффтопну. У нас ведь сегодня день программиста, не? Кто в фонтаны, господа?
      Ответить

    Добавить комментарий