From: T. V. Raman
Subject: A sticky structure accessor problem:
Date: 
Message-ID: <1992Aug9.214157.10649@cs.cornell.edu>
I am facing a rather sticky problem in some code I am writing. I will
abstract out the problem using a simple example below. 

Given a structure 
(defstruct pt  x y z) 

I am passing the structure to a function which makes a copy of the
structure, does some work, which includes setting some new values in
the local copy, and returns the local copy. 

Consider the function move-by which takes a point, a dimension and an
offset and returns a new point after moving along dimension by offset.

How do I write such a function?

Doing the following:

(defun move-by(point dimension offset) 
	...
	)

Assuming that the structure is defined using (:conc-name nil) to make
getting the accessor name easy doing 
(setf (dimension point) value) obviously fails, as does the more
correct 
(setf (funcall dimension point) ..)

Since setf complains about undefined function (setf funcall) 

I tried fixing the problem by using defsetf (mimicking the code from
																											 Norvig's book)


I tried:

(defun accessor(field structure) 
	(funcall field structure))
and 
(defsetf accessor(field structure) (value)
	`(setf (funcall ,field ,structure) ,value)
	)
but I am not able to get it working. 
I continue to get the same error message:
undefined function: (setf funcall)

Is there a clean solution to this problem? 

Thanks,

--Raman
-- 
   T. V. Raman <·····@cs.cornell.edu>Tel: (607)255-7421 R 272-2435
		       Office: 5162 Upson Hall,
Department of Computer Science, Cornell University Ithaca NY 14853-6201
		Res: 226 Bryant Avenue Ithaca NY 14850
From: Barry Margolin
Subject: Re: A sticky structure accessor problem:
Date: 
Message-ID: <1645ckINN12b@early-bird.think.com>
In article <·····················@cs.cornell.edu> ·····@cs.cornell.edu (T. V. Raman) writes:
>(defun accessor(field structure) 
>	(funcall field structure))
>and 
>(defsetf accessor(field structure) (value)
>	`(setf (funcall ,field ,structure) ,value)
>	)
>but I am not able to get it working. 
>I continue to get the same error message:
>undefined function: (setf funcall)

FUNCALL and APPLY can only be used with SETF if the function is a literal,
since SETF needs to know at macroexpansion time what to call.

>Is there a clean solution to this problem? 

You could make your structure :TYPE VECTOR, and pass the index of the
particular dimension.

You could pass the dimension as a symbol, and maintain a table mapping the
dimension names to the accessor and updater functions.  This could be
hidden in your above ACCESSOR function and defsetf:

(defvar *point-accessor-table*
  `((x ,#'point-x ,#'(lambda (point new-value) (setf (point-x point) new-value)))
    (y ,#'point-y ,#'(lambda (point new-value) (setf (point-y point) new-value)))
    (z ,#'point-z ,#'(lambda (point new-value) (setf (point-z point) new-value)))))

(defun point-accessor (field point)
  (funcall (second (assoc field *point-accessor-table*)) point))

(defsetf point-accessor (field point) (new-value)
  `(funcall (third (assoc ,field *point-accessor-table*))
	    ,point ,new-value))
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar