Common Lisp Multiple Metaclasses
Asked Answered
I

2

5

Having recently discovered an active fork of weblocks, I would like to combine it with the ORM library mito.

Weblocks defines a macro defwidget, which in practice wraps defclass like so:

(defclass my-class ()
  ((slot))
  (:metaclass weblocks/widgets/mop:widgets-class))

Meanwhile Mito works like so:

(defclass my-class ()
  ((...))
  (:metaclass mito:dao-table-class))

How can I make it so that the following works?

(defclass my-class ()
  (...))

(defvar *obj* (make-instance 'my-class))

(render *obj*) ;render from weblocks

(save-dao *obj*) ;save-dao from mito

(my-method *obj*)

I've tried inheritance, but failed in some different ways. I've only used CLOS a short time. Thus I have trouble gauging where on the spectrum

"I'm stupid <=====> This is impossible"

I am standing. Any help would be appreciated.

Insessorial answered 9/12, 2018 at 16:54 Comment(1)
Good question. I opened a related issue on Weblocks: github.com/40ants/weblocks/issues/19 Show us your progress on weblock's issue, gitter or reddit when you can !Fabiolafabiolas
B
10

I've tried inheritance, but failed in some different ways. I've only used CLOS a short time. Thus I have trouble gauging where on the spectrum ...

Don't worry, jumping straight to metaobjects with little experience with CLOS certainly is difficult, I recommend reading The Art of the Metaobject Protocol, (also known as "AMOP", by Gregor Kiczales and Jim Des Rivieres). There is an HTML version of chapters 5 and 6 by Robert Strandh at http://metamodular.com/CLOS-MOP.

You want to define a hybrid metaclass, that inherits from both metaclasses.

(defclass hybrid-metaclass (mito:dao-table-class
                            weblocks:widget-class)
  ())

If you define a class with the above metaclass, you are going to have this warning:

;; WARNING: #<HYBRID-METACLASS COMMON-LISP-USER::MY-WIDGET {100B8FE683}> is not
;; defined to be a subclass of WEBLOCKS:WIDGET; consider adding WEBLOCKS:WIDGET
;; or a subclass thereof to the superclass list

The widget-class metaclass expects all its classes to inherits from a base class, weblocks:widget.

Let's define such a base object for our hybrid metaclass:

(defclass hybrid-widget (weblocks:widget) ()
  (:metaclass hybrid-metaclass))

Here, hybrid-widget inherits from weblocks:widget, and has for metaclass hybrid-metaclass. All your widgets should inherit from this class and have for metaclass hybrid-metaclass (feel free to find a better name).

Balbo answered 9/12, 2018 at 19:46 Comment(2)
Solutions seems to work great, your help is Deeply appreciated.Insessorial
I didn't want to go into the deep end of the pool (= metaclasses) right away, but using those libraries would allow me to work on this at work, meaning learning CLOS faster. Also, I haven't seen the issue of multiple metaclasses directly addressed anywhere.Insessorial
S
3

Even if it is possible to solve as @coredump suggests, I don't recommend you to mix model (storage and business logic) and widget (representation of these objects) in one class.

Usually, I define my widget with a slot pointing to an object. This way, you can also define widgets which contain lists of objects. It is useful when making a widget for each separate object don't have a sense.

You only need to make 1-1 link between object and widget when you need to update an object's representation separately from other blocks as a response to some action, for example on marking a task as DONE.

Swagerty answered 12/12, 2018 at 20:33 Comment(1)
Thank you for your input. I am trying out different approaches to this, and my toy-app for testing has this 1-1 link. Would it be possible to add a minimal example of your approach to the reblocks tutorial?Insessorial

© 2022 - 2024 — McMap. All rights reserved.