From: Masoud Pirnazar
Subject: References or Accessors
Date: 
Message-ID: <3679472D.25F49F43@apptek-nospam-please.com>
In a piece of code such as
    (setf (gethash 'jane actors) '((age 24) (height 5)))
How can one remember the place returned by (gethash 'jane actors) to set
it to something later?
e.g. (set-accessor pos1 (gethash 'jane actors)), and later do (setf pos1
'((age 24) (height 5)))



Similarly for classes (and structures), instead of doing
    (setf (slot-value employee-record 'name) "Jane")
I'd like to do
    (set-accessor pos1 (slot-value employee-record 'name))
then later do
    (setf pos1 'name)


Please respond to ···@apptek.com
--Masoud Pirnazar

From: Barry Margolin
Subject: Re: References or Accessors
Date: 
Message-ID: <R4de2.66$pr1.5636@burlma1-snr1.gtei.net>
In article <·················@apptek-nospam-please.com>,
Masoud Pirnazar  <···@apptek.com> wrote:
>In a piece of code such as
>    (setf (gethash 'jane actors) '((age 24) (height 5)))
>How can one remember the place returned by (gethash 'jane actors) to set
>it to something later?
>e.g. (set-accessor pos1 (gethash 'jane actors)), and later do (setf pos1
>'((age 24) (height 5)))

There isn't such a thing.  Symbolics Lispms have locatives, which are kind
of like pointers except they interact with GC properly, and (locf <place>)
returns a locative to the place.  However, I think this only works for
places that identify a single storage location, e.g. (locf (cdr thing)) or
(locf (aref ...)); since a hash table can be rehashed as it grows, I don't
think it works with GETHASH (it will continue to refer to the same storage
in the hash table's internal array, which the key may no longer hash to).

The only simple way to do what you want in standard CL is with EVAL:

(setq place '(gethash 'jane actors))
(eval `(setf ,place '((age 24) (height 5))))

Note that this loses lexical scoping -- if actors was a local variable,
EVAL won't be able to access it.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Don't bother cc'ing followups to me.
From: Stig Hemmer
Subject: Re: References or Accessors
Date: 
Message-ID: <ekvd85ictsk.fsf@verden.pvv.ntnu.no>
Barry Margolin <······@bbnplanet.com> writes:
> In article <·················@apptek-nospam-please.com>,
> Masoud Pirnazar  <···@apptek.com> wrote:
> >(set-accessor pos1 (gethash 'jane actors))
> > (setf pos1 '((age 24) (height 5)))
>
> The only simple way to do what you want in standard CL is with EVAL:
> 
> (setq place '(gethash 'jane actors))
> (eval `(setf ,place '((age 24) (height 5))))

A non-simple way, using a macro:

(defmacro make-accessor (place)
  "Returns a lambda that setf's PLACE to its argument."
  `(lambda (value) (setf ,place value)))

(defun setf-through-accessor (accessor value)
  "Set the place stored in ACCESSOR equal to VALUE."
  (funcall accessor value))

Well, the macro isn't very nice because it doesn't work if PLACE
contains a variable called VALUE.  This is easily solved using
(GENSYM), but I thought I should show the above version first for ease
of understanding.

(GENSYM) version:

(defmacro make-accessor (place)
  (let ((symbol (gensym)))
    `(lambda (,symbol) (setf ,place ,symbol))))

If you want to use the accessor to get the value as well as setting
it, you would need to something a bit more complicated, but not very
much so.  Hint: (CONS) two lambdas together. (CAR)/(CDR) out the one
you want, as needed.

Hmm... another problem:  If you do something like:

(setf pos1 (make-accessor (gethash name actors)))

and the later changes the varible NAME, (SETF-THROUGH-ACCESSOR) will
use the _new_ value of the variable.  This is probably not what you
had in mind, but is harder to fix.

Hope this helps.

Stig Hemmer,                    "emacs - the swiss army sledgehammer"
Jack of a Few Trades.                                  Johan Kullstam