From: Rene de Visser
Subject: Setf and reading function: How to avoid duplication of code?
Date:
Message-ID: <a128it$itt$1@news1.wdf.sap-ag.de>
How can the following be improved?
One option would be to use a macro to generate both classify and (setf
classify), but this seems like unnessary complexitiy.
Ideally I would like to just write (setf classify) and somehow derive
classify from it.
I have several times written read and set (setf) routines and then had the
problem of having most of the code duplicated between the reading and
setting functions. Is there a better way?
(defstruct mystructure
var1
var2
var3
var4)
(defun (setf classify) (value structure color)
(ecase color
(#\B (setf (mystructure-var1 structure) value))
(#\W (setf (mystructure-var2 structure) value))
('(#\G #\R) (setf (mystructure-var3 structure) value))
(t (setf (mystructure-var4 structure) value))))
(defun classify (structure color)
(ecase color
(#\B (mystructure-var1 structure))
(#\W (mystructure-var2 structure))
('(#\G #\R) (mystructure-var3 structure))
(t (mystructure-var4 structure))))
(let ((structure (make-mystructure)))
(setf (classify structure #\B ) 100)
(classify structure #\B))
In article <············@news1.wdf.sap-ag.de>, "Rene de Visser"
<··············@hotmail.de> wrote:
>How can the following be improved?
>
>(defun (setf classify) (value structure color)
> (ecase color
> (#\B (setf (mystructure-var1 structure) value))
> (#\W (setf (mystructure-var2 structure) value))
> ('(#\G #\R) (setf (mystructure-var3 structure) value))
I don't think you want the quote here.
> (t (setf (mystructure-var4 structure) value))))
This is illegal. ECASE doesn't permit else clauses. Use CASE.
>(defun classify (structure color)
> (ecase color
> (#\B (mystructure-var1 structure))
> (#\W (mystructure-var2 structure))
> ('(#\G #\R) (mystructure-var3 structure))
> (t (mystructure-var4 structure))))
>
>(let ((structure (make-mystructure)))
> (setf (classify structure #\B ) 100)
> (classify structure #\B))
Do you have a reason for a structure? Or is it the form of
the example you need to support. If the latter, I'd do this:
(defmacro classify (data color)
`(aref ,data (get-color-index ,color)))
(defun get-color-index (color)
(case color
(#\B 0)
(#\W 1)
((#\G #\R) 2)
(t 3)))
(let ((data (make-array 4)))
(setf (classify data #\B ) 100)
(classify data #\B))
From: Barry Margolin
Subject: Re: Setf and reading function: How to avoid duplication of code?
Date:
Message-ID: <ui7Z7.2$Tr2.20883@burlma1-snr2>
In article <············@news1.wdf.sap-ag.de>,
Rene de Visser <··············@hotmail.de> wrote:
>How can the following be improved?
>
>One option would be to use a macro to generate both classify and (setf
>classify), but this seems like unnessary complexitiy.
>Ideally I would like to just write (setf classify) and somehow derive
>classify from it.
Lisp isn't a logic language, it doesn't automatically work out derivations
like this. SETF isn't a magic bullet, it's just a common notation for
assignment operators -- you still have to tell the system how to perform
the assignment.
>I have several times written read and set (setf) routines and then had the
>problem of having most of the code duplicated between the reading and
>setting functions. Is there a better way?
>
>(defstruct mystructure
> var1
> var2
> var3
> var4)
>
>(defun (setf classify) (value structure color)
> (ecase color
> (#\B (setf (mystructure-var1 structure) value))
> (#\W (setf (mystructure-var2 structure) value))
> ('(#\G #\R) (setf (mystructure-var3 structure) value))
> (t (setf (mystructure-var4 structure) value))))
>
>(defun classify (structure color)
> (ecase color
> (#\B (mystructure-var1 structure))
> (#\W (mystructure-var2 structure))
> ('(#\G #\R) (mystructure-var3 structure))
> (t (mystructure-var4 structure))))
(defconstant +mystructure-slot-alist+
`((var1 ,#'mystructure-var1 #'(setf mystructure-var1))
(var2 ,#'mystructure-var2 #'(setf mystructure-var2))
(var3 ,#'mystructure-var3 #'(setf mystructure-var3))
(var4 ,#'mystructure-var4 #'(setf mystructure-var4)))
"Alist mapping MYSTRUCTURE slot names to getter and setter")
(defun color-to-slot (color)
(case color
(#\B 'var1)
(#\W 'var2)
((#\G #\R) 'var3)
(t 'var4)))
(defun mystructure-reader (color)
(second (assoc (color-to-slot color) +mystructure-slot-alist+)))
(defun mystructure-setter (color)
(third (assoc (color-to-slot color) +mystructure-slot-alist+)))
(defun (setf classify) (value structure color)
(apply (mystructure-setter color) value structure))
(defun classify (structure color)
(apply (mystructure-reader color) structure))
All that alist stuff could be done away with if you used a class instead of
a structure. Then you could do:
(defun mystructure-reader (color)
(fdefinition (color-to-slot color)))
(defun mystructure-setter (color)
(fdefinition `(setf ,(color-to-slot color))))
Or you could use SLOT-VALUE instead of the generic functions to access the
slots:
(defun (setf classify) (value structure color)
(setf (slot-value structure (color-to-slot color)) value)
(defun classify (structure color)
(slot-value structure (color-to-slot color)))
--
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.