From: ·········@yahoo.com
Subject: Updating struct value(s) using macro call from function
Date: 
Message-ID: <1158976546.774161.26270@k70g2000cwa.googlegroups.com>
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))

From: Pascal Bourguignon
Subject: Re: Updating struct value(s) using macro call from function
Date: 
Message-ID: <87fyej49mu.fsf@thalassa.informatimago.com>
·········@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)))
From: ·········@yahoo.com
Subject: Re: Updating struct value(s) using macro call from function
Date: 
Message-ID: <1159010575.814170.317580@i42g2000cwa.googlegroups.com>
Pascal Bourguignon wrote:
> ·········@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)))

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 .
From: Alan Crowe
Subject: Re: Updating struct value(s) using macro call from function
Date: 
Message-ID: <86wt7u672j.fsf@cawtech.freeserve.co.uk>
·········@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
From: Pascal Bourguignon
Subject: Re: Updating struct value(s) using macro call from function
Date: 
Message-ID: <87zmcq38ge.fsf@thalassa.informatimago.com>
·········@yahoo.com writes:

> Pascal Bourguignon wrote:
>> ·········@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!"