From: Rui Maciel on
Let's say we have a set of lists. Is there a way to trigger specific actions by not only operating on those
lists (i.e., push'ing and pop'ing) but also tweaking it's values?


Thanks in advance,
Rui Maciel
From: Pascal J. Bourguignon on
Rui Maciel <rui.maciel(a)gmail.com> writes:

> Let's say we have a set of lists. Is there a way to trigger specific
> actions by not only operating on those lists (i.e., push'ing and
> pop'ing) but also tweaking it's values?

(let ((fruits (list 'apple 'orange 'cranberry)))
(setf (third fruits) 'banana)
fruits)

(let ((fruits (list 'apple 'orange 'cranberry)))
(setf (nth 2 fruits) 'banana)
fruits)

But be careful that these lists are all built only from mutable parts
(ie. use LIST, not QUOTE), if you want to mutate them like this.

--
__Pascal Bourguignon__
From: Alex Mizrahi on
RM> Let's say we have a set of lists. Is there a way to trigger specific
RM> actions by not only operating on those lists (i.e., push'ing and
RM> pop'ing) but also tweaking it's values?

"Trigger action" as in observer pattern? No, it is possible only
with classes.


From: Rui Maciel on
Alex Mizrahi wrote:

> "Trigger action" as in observer pattern? No, it is possible only
> with classes.

Could you please provide an example?


Thanks in advance,
Rui Maciel
From: Alex Mizrahi on
??>> "Trigger action" as in observer pattern? No, it is possible only
??>> with classes.

RM> Could you please provide an example?

I'm not sure I undertstand your question correctly. Do you want
to recieve some sort of notification when something changes
list entries?

It is possible to do this by re-implementing lists in CLOS.
Here's example how one can implement observable conses
and some list API on top of them: http://paste.lisp.org/display/89244

Then it will sort of work:

CL-USER> (in-package :obs-test)
#<PACKAGE "OBS-TEST">
OBS-TEST> (setf *observer* (make-instance 'logging-observer))
#<LOGGING-OBSERVER {B3A4D01}>
OBS-TEST> (defparameter *list* (list 1 2 3 4))
*LIST*
OBS-TEST> *list*
#<1 . #<2 . #<3 . #<4 . NIL>>>>
OBS-TEST> (second *list*)
2
OBS-TEST> (setf (second *list*) 'b)
`CAR` of `#<2 . #<3 . #<4 . NIL>>>` is going to change from `2` to `B`
B
OBS-TEST> *list*
#<1 . #<B . #<3 . #<4 . NIL>>>>

But it won't work for more complex cases, won't work with PUSH/POP (unless
you invent some trick),
and I doubt it has any practical value.

But I hope you've got an idea -- if you want to track writes to some slots
via accessors,
implement (setf accessorname) :before or :after method.

This won't work with (setf (slot-name ....)) though, if you want it to work
then
you probably need to deal with metaclasses or something like that.

Also there are few libs which can help with observers and stuff. Cells among
them.