Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Updating struct value(s) using macro call from function

64 views
Skip to first unread message

marc...@yahoo.com

unread,
Sep 22, 2006, 9:55:46 PM9/22/06
to
If I call the field macro from toplevel it works ok;
but it fails when I try to embed it in foo--how to fix this?

(defstruct (struc (:conc-name nil)) a b))

(defparameter s (make-struc :a 1 :b 2))

(defmacro field (struc fld val)
`(setf (,fld ,struc) ,val ))

(defun foo (s f)
(let ((value nil))
(format t "~A> " f)
(setf value (read))
(field s f value)))

CL-USER> (foo s 'a)
A> 34
==>(FUNCTION: undefined function #1=(SETF F))

I want functionality similar to below. However,
I want to update struct values, not just return a list:


(defparameter ldep '(name age ssn child-tax-credit?))
(defstruct (dep (:conc-name nil)) name age ssn child-tax-credit?)
(defparameter dep (make-dep :name "nobody" :age 136))
(setf (child-tax-credit? dep) 'yes)

(defun get-input (section)
(setf *inputs* (mapcar #'input section)))
(defun input(field)
(let ((prompt nil))
(format t "~A> " field)
(setf prompt (read))
(list field prompt)))


CL-USER> (get-input ldep)
NAME> "mr smith"
AGE> 34
SSN> "xxx"
CHILD-TAX-CREDIT?> 'no

((NAME "mr smith") (AGE 34) (SSN "xxx") (CHILD-TAX-CREDIT? 'NO))

Pascal Bourguignon

unread,
Sep 22, 2006, 10:08:57 PM9/22/06
to
marc...@yahoo.com writes:

> If I call the field macro from toplevel it works ok;
> but it fails when I try to embed it in foo--how to fix this?

Have a look at:

http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/24af86e25777fa0c/34681fc951fb42b2?lnk=st&q=defmacro+defstruct+case+group%3Acomp.lang.lisp+&rnum=7&hl=en#34681fc951fb42b2


--
__Pascal Bourguignon__ http://www.informatimago.com/

"This statement is false." In Lisp: (defun Q () (eq nil (Q)))

marc...@yahoo.com

unread,
Sep 23, 2006, 7:22:55 AM9/23/06
to

But I am able to access the slot names. I just want to know how to
update a slot value for a function that accepts a struc and slot
parameter .

Alan Crowe

unread,
Sep 23, 2006, 9:33:40 AM9/23/06
to
marc...@yahoo.com writes:
> But I am able to access the slot names. I just want to know how to
> update a slot value for a function that accepts a struc and slot
> parameter .

CL-USER> (defstruct example x y)
EXAMPLE

CL-USER> (defparameter structure (make-example :x 'old-x :y 'old-y))
STRUCTURE

CL-USER> structure
#S(EXAMPLE :X OLD-X :Y OLD-Y)

CL-USER> (funcall (fdefinition (list 'setf (progn (format t "~&Where? ")
(read))))
'new-value structure)
Where? example-y

NEW-VALUE

CL-USER> structure
#S(EXAMPLE :X OLD-X :Y NEW-VALUE)

Using fdefinition to retrieve the structure's slot writer at
run time so that it can be funcalled is clunky. I presume
that the design of CL intends that you use CLOS for this
kind of thing.

CL-USER> (defclass example2 ()
((x :initarg :x)
(y :initarg :y)))
#<STANDARD-CLASS EXAMPLE2 {48B6F92D}>

CL-USER> (defparameter class (make-instance 'example2 :x 'old-x :y 'old-y))
CLASS

CL-USER> (describe class)

#<EXAMPLE2 {4800F9E5}> is an instance of class #<STANDARD-CLASS EXAMPLE2
{48B6F92D}>:
The following slots have :INSTANCE allocation:
X OLD-X
Y OLD-Y

CL-USER> (setf (slot-value class (progn (format t "~&Where? ")
(read)))
'new-value)
Where? y
NEW-VALUE

CL-USER> (describe class)

#<EXAMPLE2 {4800F9E5}> is an instance of class #<STANDARD-CLASS EXAMPLE2
{48B6F92D}>:
The following slots have :INSTANCE allocation:
X OLD-X
Y NEW-VALUE

Alan Crowe
Edinburgh
Scotland

Pascal Bourguignon

unread,
Sep 23, 2006, 11:32:01 AM9/23/06
to
marc...@yahoo.com writes:

> Pascal Bourguignon wrote:
>> marc...@yahoo.com writes:
>>
>> > If I call the field macro from toplevel it works ok;
>> > but it fails when I try to embed it in foo--how to fix this?
>>
>> Have a look at:
>>
>> http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/24af86e25777fa0c/34681fc951fb42b2?lnk=st&q=defmacro+defstruct+case+group%3Acomp.lang.lisp+&rnum=7&hl=en#34681fc951fb42b2
>

> But I am able to access the slot names. I just want to know how to
> update a slot value for a function that accepts a struc and slot
> parameter .

You have the right to think a little, and to program.

(defmacro defstruct* (opts &rest slots)
(let ((slot-list (mapcar (lambda (s) (if (consp s) (car s) s)) slots))
(struct-name opts)
(conc-name nil)
(include nil))
(cond ((consp opts)
(setf struct-name (car opts)
include (second (assoc :INCLUDE (cdr opts)))
conc-name (second (assoc :CONC-NAME (cdr opts))))
(if conc-name
(setf conc-name (format nil "~A" conc-name))
(setf conc-name (format nil "~A-" struct-name)))
(when include
(setf slot-list (append (structure-slot-names include) slot-list))))
(t (setf conc-name (setf conc-name (format nil "~A-" struct-name)))))
`(progn
(setf (get ',struct-name 'original-defstruct-slots)
(list
,@(mapcar
(lambda (s)
(let ((accessor (intern (format nil "~A~A" conc-name s))))
`(list ',s
(function ,accessor)
(function (setf ,accessor)))))
slot-list)))
(defstruct ,opts ,@slots))))

(defun structure-slot-readers (structure-name)
"Given the name of structure, return the reader functions."
(mapcar (function second) (structure-slot-alist structure-name)))

(defun structure-slot-reader (structure-name slot-name)
"Given the name of a structure and a slot, return reader functions."
(second (assoc slot-name (structure-slot-alist structure-name))))

(defun structure-slot-writers (structure-name)
"Given the name of structure, return the reader functions."
(mapcar (function third) (structure-slot-alist structure-name)))

(defun structure-slot-writer (structure-name slot-name)
"Given the name of a structure and a slot, return reader functions."
(third (assoc slot-name (structure-slot-alist structure-name))))


(defun field-value (structure field)
(funcall (structure-slot-reader (type-of structure) field) structure))

(defun (setf field-value) (value structure field)
(funcall (structure-slot-writer (type-of structure) field) value structure))


LISP> (defparameter *p* (make-phew))
*P*
LISP> (field-value *p* 'baz)
1
LISP> (setf (field-value *p* 'baz) 2)
2
LISP> *p*
#S(PHEW :BAR NIL :BAZ 2 :BEAR NIL :BAHS NIL)


(defun list-all-structure-slots (struct name)
(mapcar (lambda (accessor) (funcall accessor struct))
(structure-slot-readers name)))


LISP> (list-all-structure-slots *p* (type-of *p*))
(NIL 2 NIL NIL)


--
__Pascal Bourguignon__ http://www.informatimago.com/

"You question the worthiness of my code? I should kill you where you
stand!"

0 new messages