Hi, I have following scenario - I want to get more than one slot value of object, but pay for dispatch just once. Is there a function in CL which allows you to dispatch once on the object type, and then get a values of different slots? I don't mean with-slots, since that expands (in SBCL) to symbol- macrolets using slot-value, and every time you use the slot-name, it expands to (slot-value ...) which pays for dispatch.
where x and y in the body of with-bound-values-from-slots are bound to variable using multiple-value-bind for example and values of those x and y are taken from the object in one step.
> Hi, > I have following scenario - I want to get more than one slot value > of object, but pay for dispatch just once. > Is there a function in CL which allows you to dispatch once on the > object type, and then get a values of different slots? > I don't mean with-slots, since that expands (in SBCL) to symbol- > macrolets using slot-value, and every time you use the slot-name, it > expands to (slot-value ...) which pays for dispatch.
> where x and y in the body of with-bound-values-from-slots are bound to > variable using multiple-value-bind for example and values of those x > and y are taken from the object in one step.
> Karol
Note that SLOT-VALUE is a function, not a generic function.
Karol Skocik <Karol.Sko...@gmail.com> writes: > Hi, > I have following scenario - I want to get more than one slot value > of object, but pay for dispatch just once. > Is there a function in CL which allows you to dispatch once on the > object type, and then get a values of different slots? > I don't mean with-slots, since that expands (in SBCL) to symbol- > macrolets using slot-value, and every time you use the slot-name, it > expands to (slot-value ...) which pays for dispatch.
> where x and y in the body of with-bound-values-from-slots are bound to > variable using multiple-value-bind for example and values of those x > and y are taken from the object in one step.
* Karol Skocik Wrote on Sat, 17 Jan 2009 03:18:32 -0800 (PST):
| I have following scenario - I want to get more than one slot value of | object, but pay for dispatch just once. Is there a function in CL | which allows you to dispatch once on the object type, and then get a | values of different slots? I don't mean with-slots, since that | expands (in SBCL) to symbol- macrolets using slot-value, and every | time you use the slot-name, it expands to (slot-value ...) which pays | for dispatch. | | I mean something like: | | (with-bound-values-from-slots ((x slot-name-x) (y slot-name-y)) object | ...) | | where x and y in the body of with-bound-values-from-slots are bound to | variable using multiple-value-bind for example and values of those x | and y are taken from the object in one step. |
Others have pointed out that there is nothing wrong with WITH-SLOTS and there should be no reason to avoid it.
However if you want to avoid the SYMBOL-MACROLET in WITH-SLOTS altogether (maybe you do not ever want to set the slot value) in the body, you can just use
And replace the SYMBOL-MACROLET with LET in the expansion --- and use that literally in your code.
I do have a macro which does this, but I won't post it because I think it is abuse. [Actually I abuse it in another way: for accessing slot-names that are in a different package without importing the symbols or qualifying the package name explicitly]
> Karol Skocik <Karol.Sko...@gmail.com> writes: > > Hi, > > I have following scenario - I want to get more than one slot value > > of object, but pay for dispatch just once. > > Is there a function in CL which allows you to dispatch once on the > > object type, and then get a values of different slots? > > I don't mean with-slots, since that expands (in SBCL) to symbol- > > macrolets using slot-value, and every time you use the slot-name, it > > expands to (slot-value ...) which pays for dispatch.
> > where x and y in the body of with-bound-values-from-slots are bound to > > variable using multiple-value-bind for example and values of those x > > and y are taken from the object in one step.
> (multiple-value-bind (x y ... z) (slots object) > ...)
> One single dispatch (but as Rainer mentionned, you can do it with zero > dispatch).
> -- > __Pascal Bourguignon__
I think I did not formed my question clearly. I was after built-in way (directly in CL) how to avoid even slot-value. Every slot-value function has to somehow get the layout of class first and then check for the presence of slot specified by symbol.
What I wanted is: Get the layout first *once*, and then with that layout check for presence of slots, finally when all slots are present return all of them with values.
Karol Skocik wrote: > On Jan 17, 1:18 pm, p...@informatimago.com (Pascal J. Bourguignon) > wrote: >> Karol Skocik <Karol.Sko...@gmail.com> writes: >>> Hi, >>> I have following scenario - I want to get more than one slot value >>> of object, but pay for dispatch just once. >>> Is there a function in CL which allows you to dispatch once on the >>> object type, and then get a values of different slots? >>> I don't mean with-slots, since that expands (in SBCL) to symbol- >>> macrolets using slot-value, and every time you use the slot-name, it >>> expands to (slot-value ...) which pays for dispatch. >>> I mean something like: >>> (with-bound-values-from-slots ((x slot-name-x) (y slot-name-y)) object >>> ...) >>> where x and y in the body of with-bound-values-from-slots are bound to >>> variable using multiple-value-bind for example and values of those x >>> and y are taken from the object in one step. >> (defmethod slots ((object class)) >> (values (slot-value object 'slot-1) >> (slot-value object 'slot-2) >> ... >> (slot-value object 'slot-n)))
>> (multiple-value-bind (x y ... z) (slots object) >> ...)
>> One single dispatch (but as Rainer mentionned, you can do it with zero >> dispatch).
>> -- >> __Pascal Bourguignon__
> I think I did not formed my question clearly. I was after built-in way > (directly in CL) how to avoid even slot-value. Every slot-value > function has to somehow get the layout of class first and then check > for the presence of slot specified by symbol.
Note that CLOS slots are more inefficient than structs primarily because of the fact CLOS slots can be unbound and each and every slot access has to check for that condition. (Some implementations allow you to declare that you don't want this, like CMUCL.)
Also see standard-instance-access, which is part of the CLOS MOP and which allows you to circumvent all additional checks CLOS has to perform (and is therefore a somewhat dangerous tool that should be used wisely).
Karol Skocik <Karol.Sko...@gmail.com> writes: > On Jan 17, 1:18 pm, p...@informatimago.com (Pascal J. Bourguignon) > wrote: >> Karol Skocik <Karol.Sko...@gmail.com> writes: >> > Hi, >> > I have following scenario - I want to get more than one slot value >> > of object, but pay for dispatch just once. >> > Is there a function in CL which allows you to dispatch once on the >> > object type, and then get a values of different slots? >> > I don't mean with-slots, since that expands (in SBCL) to symbol- >> > macrolets using slot-value, and every time you use the slot-name, it >> > expands to (slot-value ...) which pays for dispatch.
>> > where x and y in the body of with-bound-values-from-slots are bound to >> > variable using multiple-value-bind for example and values of those x >> > and y are taken from the object in one step.
>> (multiple-value-bind (x y ... z) (slots object) >> ...)
>> One single dispatch (but as Rainer mentionned, you can do it with zero >> dispatch).
>> -- >> __Pascal Bourguignon__
> I think I did not formed my question clearly. I was after built-in way > (directly in CL) how to avoid even slot-value. Every slot-value > function has to somehow get the layout of class first and then check > for the presence of slot specified by symbol.
> What I wanted is: Get the layout first *once*, and then with that > layout check for presence of slots, finally when all slots are present > return all of them with values.
With CLOS, you cannot avoid SLOT-VALUE:
(defun f (o) (change-class o 'some-other-class))
(with-slots (x y z) o (setf x (do-something x y z)) (f o) (setf x (do-something x y z)))
In CL implementations with threads, it's even worse:
(with-slots (x y z) o (setf x (do-something x y z)) ;; Here another thread may change the class of o. (setf x (do-something x y z)))
If you want to avoid SLOT-VALUE, you must use another object system.
You could try first DEFSTRUCT. Here, redefining a structure class has undefined effects, so you don't do that in conformant code.
Otherwise, just write your own object system or use a library OO system (eg. KR, but I don't think you'll like it).
> Karol Skocik wrote: > > On Jan 17, 1:18 pm, p...@informatimago.com (Pascal J. Bourguignon) > > wrote: > >> Karol Skocik <Karol.Sko...@gmail.com> writes: > >>> Hi, > >>> I have following scenario - I want to get more than one slot value > >>> of object, but pay for dispatch just once. > >>> Is there a function in CL which allows you to dispatch once on the > >>> object type, and then get a values of different slots? > >>> I don't mean with-slots, since that expands (in SBCL) to symbol- > >>> macrolets using slot-value, and every time you use the slot-name, it > >>> expands to (slot-value ...) which pays for dispatch. > >>> I mean something like: > >>> (with-bound-values-from-slots ((x slot-name-x) (y slot-name-y)) object > >>> ...) > >>> where x and y in the body of with-bound-values-from-slots are bound to > >>> variable using multiple-value-bind for example and values of those x > >>> and y are taken from the object in one step. > >> (defmethod slots ((object class)) > >> (values (slot-value object 'slot-1) > >> (slot-value object 'slot-2) > >> ... > >> (slot-value object 'slot-n)))
> >> One single dispatch (but as Rainer mentionned, you can do it with zero > >> dispatch).
> >> -- > >> __Pascal Bourguignon__
> > I think I did not formed my question clearly. I was after built-in way > > (directly in CL) how to avoid even slot-value. Every slot-value > > function has to somehow get the layout of class first and then check > > for the presence of slot specified by symbol.
> Note that CLOS slots are more inefficient than structs primarily because > of the fact CLOS slots can be unbound and each and every slot access has > to check for that condition. (Some implementations allow you to declare > that you don't want this, like CMUCL.)
> Also see standard-instance-access, which is part of the CLOS MOP and > which allows you to circumvent all additional checks CLOS has to perform > (and is therefore a somewhat dangerous tool that should be used wisely).
> Hi, > I have following scenario - I want to get more than one slot value > of object, but pay for dispatch just once. > Is there a function in CL which allows you to dispatch once on the > object type, and then get a values of different slots? > I don't mean with-slots, since that expands (in SBCL) to symbol- > macrolets using slot-value, and every time you use the slot-name, it > expands to (slot-value ...) which pays for dispatch.
> where x and y in the body of with-bound-values-from-slots are bound to > variable using multiple-value-bind for example and values of those x > and y are taken from the object in one step.
> Karol
You could use WITH-ACCESSORS - it uses the generated accessor functions of your CLOS classes. In some implementations of CLOS an accessor doesn't have to go through SLOT-VALUE-USING-CLASS; accessors would then be faster than using SLOT-VALUE with a symbol. SLOT-VALUE itself could also get optimized quite well for constant slot-name parameters. Actually your problem doesn't actually is object accesses but really creating bindings to values based on a snapshot of the objects state at that time. There is nothing like this in standard common lisp - but isn't that quite trivial?
(defmacro with-bound-values-from-slots (bindings object &body forms) `(with-slots ,bindings object (let ,(loop for (b _) in bindings collect (list b b)) ,@forms)))