libera/#commonlisp - IRC Chatlog
Search
17:38:25
Bike
what that function does is take all the direct slot definitions from the class precedence list, and combine them together into an effective slot definition
17:39:04
Bike
This is necessary because there's no obvious way to combine inherited slot information; even the standard slot options inherit in all kinds of different ways http://www.lispworks.com/documentation/lw70/CLHS/Body/07_ec.htm
17:39:45
Bike
it's been a while, but iirc your method should do call-next-method and then set the metadata slots in the result appropriately
17:39:47
mfiano
I see. So once I do all of this, what is the correct way to query the encoder/decoder functions of one of my leaf class instances?
17:40:36
Bike
You get at the slot definition (e.g. through class-slots) and then use your ENCODER and DECODER accessors
17:41:35
Bike
https://github.com/yitzchak/common-lisp-jupyter/blob/master/src/widgets/traits.lisp#L33-L73 here's some code in cl jupyter that defines a new slot class
17:43:41
Bike
in this case, the inheritance rules are simple: the most recent wins. your encoder and decoder might work the same way
17:44:15
Bike
also, iirc, you might have problems specifying them in the way you do. i don't think the slot definition initargs are evaluated, so the direct slots will just have the list (FUNCTION IDENTITY) instead of an actual function
17:48:22
Bike
i think i ran into this in my initial version of this cl jupyter code (it has since been totally rewritten by yitzi) which had observer functions, and i just had it take symbols instead. so you'd write :observer foo instead of :observer #'foo
17:48:56
Bike
well, basically, imagine you have a class foo that defines (%a :encoder #'x), and then a class bar that defines (%a :encoder #'y), and then say bar inherits from foo
17:50:05
mfiano
Well in my case there won't ever be subclasses of a zfs-property class, but I would expect the deepest subclass to win in almost all cases.
17:50:28
Bike
the GF receives the direct slots in class precedence order, so using SOME like this is kosher
17:54:20
mfiano
So if I wanted it to behave like any other initarg value, how would I accomplish that?
17:56:14
Bike
well, the others have funny behavior as well. like if you have an :initarg, it's not evaluated right off, it's saved and then evaluated each time you instantiate an instance
17:56:29
Bike
I don't think you can change the behavior of the defclass macro to make it be evaluated like you want, unfortunately
17:56:34
Arthur
I ended up hacking together some c2mop:compute-effective-slot-definition stuff when encountering the #'fn non-evaluated slot inits over in https://github.com/arthev/spiclum/blob/master/src/prevalence-class.lisp, maybe there are better ways
17:57:28
Bike
you can ofc define your own defclass macro, but that can be sort of a pain in its own way
17:57:59
mfiano
Can I use the mop to get a single class slot, or do I have to use #'find or whatnot?
17:58:31
Bike
if you mean you want to get a particular slot definition from a class, you do need to use find or something yeah
17:59:15
mfiano
instead of #'c2mop:class-slots <class> -> list, something like #'foo:class-slot <class> <slot-name> -> #<esd>
18:04:17
mfiano
THe MOP always impresses me at its flexibility at the cost of boilerplate. It's to CLOS as macros are to code. Not much you can't do with CL with those two powers combined :)
18:56:41
trev
does anyone know a plugin for emacs where you can basically hover over keywords or functions and see docs for them?
19:06:12
mfiano
Anyone know if alexandria or some utility library has a shorthand for (setf (slot-value instance slot-name) (call-some-func (slot-value instance slot-name))) ?
19:09:52
mfiano
They can, but in this case it won't work anyway as slot-name is not known at compile time.
19:10:51
mfiano
THey can also be a source of serious performance issues if you are evaluating an expensive accessor effective method each read of the symbol.
19:26:57
Bike
now that i'm thinking about it, maybe it would be nice if alexandria or something had a macro like atomic-update but without the atomicity
19:36:51
_death
that's kinda like PG's _f macro in On Lisp.. I don't think it's so nice.. instead I prefer to name the operation, like INCF
19:48:01
Alfr
Bike, not in the library, but here: (defun %update (thing fun &rest args) (apply fun thing args)) (define-modify-macro update (fun &rest args) %update)
20:05:46
mfiano
Not that I think I'd need to do type-checking considering the stringified source data is coming from the correct application I am parsing into lisp objects, but it makes me wonder if I should anyway.
20:07:50
mfiano
Like one slot is fed any of "none"i, "available", "unavailable", and encoded as any of :none, :available, :unavailable. But if my program logic is wrong and tries creating an instance with bad data, I have no way to type check.
20:10:11
mfiano
Though not sure if it makes sense to type check decoding if it is symmetric with the input.
20:14:08
mfiano
I'm also not sure if it even makes sense to specify an :encoder _and_ :decoder slot. The decoder just puts it into the original form it was encoded from. That logic can be derived with a closure or object representing the transcoding method.
20:19:25
mfiano
My plan was to build a CST, producing an AST afterwards to do type-checking/generation phases on. I think I need to sketch out the pipeline better...it might be overly complex like all my compiler theory implementations are :/
21:43:03
Guest74
ugh, I hate when you can't interrupt a slime repl. This is why I shouldn't have my editor in the same process, let alone my window manager.
1:45:25
Josh_2
Does anyone have an example of using multiple :around methods combined with call-next-method?
1:45:53
Josh_2
I only just realized that call-next-method when inside of an :around looks for the next most applicable :around method before executing the primary (by default) :facepalm:
2:21:23
zacque
Josh_2: You can play around with it using hierarchical classes like animal, dog, poodle, cat, persian-cat
2:22:23
zacque
Then define a generic function like MAKE-SOUND or PRINT-NAME for specialising it on different classes
2:24:18
zacque
The trick in understanding the `Standard Method Combination` is to understand the interplay of "shadowing" and "accumulative" effects for both primary and auxiliary methods
2:25:29
Josh_2
I though (call-next-method) invokes the primary method when in :around, but it doesn't, it looks for the next most applicable :around and if it doesn't find one then it calls the most applicable primary
2:27:41
zacque
Also, I suppose you can always define a "non-crazy" order with DEFINE-METHOD-COMBINATION
2:28:34
Bike
but usually if i don't understand a method combination thing i just figure out what the form looks like based on the method combination definition
2:30:11
Bike
like if your applicable methods are two arounds, two primaries, a before, and an after, what you get is (call-method #<around1> #<around2> (make-method (progn (call-method #<before>) (multiple-value-prog1 (call-method #<primary1> #<primary2>) (call-method #<after>)))))
2:31:00
Bike
in other words, if you use call-next-method and the next method is an around, you call that, but otherwise you call the whole before/primary/after situation
2:35:06
Bike
if you get this system https://github.com/sellout/method-combination-utilities you can use method-combination-expand to get that tree i wrote out manually