GETF doesn't work for plist like lists where the keys are strings or
something else that can't be compared with eql. So I wrote my own
function that is supposed to work the same way using equal instead.
That is, have an optional default return value and also be a place for
SETF. After some searching through the CLHS, I came up with this:
(defun getfs (plist str &optional (default nil))
(if plist
(if (equal (car plist) str)
(cadr plist)
(getfs (cddr plist) str default))
default))
(defun setfs (plist str value)
(if (equal (car plist) str)
(setf (cadr plist) value)
(if (cddr plist)
(setfs (cddr plist) str value)
(progn
(nconc plist (list str value))
value))))
(defsetf getfs setfs)
This code seems to work, but I was wondering whether there was a
better way to write it. Also, it seems odd to now go ahead and have a
form like
(setf (getfs foo bar) value)
when
(setfs foo bar value)
does the same thing.
What do more experienced Lispers do when they need a function that can
also be used with SETF? I noticed there is also a long form for
DEFSETF which I haven't tried playing with yet. It took me long
enough to get SETFS to work when the key didn't exist, ie add a new
key value pair.
--
An ideal world is left as an excercise to the reader.
--- Paul Graham, On Lisp 8.1
David Steuber wrote:
> This code seems to work, but I was wondering whether there was a
> better way to write it. Also, it seems odd to now go ahead and have
a
> form like
>
> (setf (getfs foo bar) value)
>
> when
>
> (setfs foo bar value)
>
> does the same thing.
>
> What do more experienced Lispers do when they need a function that
can
> also be used with SETF? I noticed there is also a long form for
> DEFSETF which I haven't tried playing with yet. It took me long
> enough to get SETFS to work when the key didn't exist, ie add a new
> key value pair.
>
I haven't really looked at your stuff, but for simple things I use
(defun (setf x) (new ...) ...)
which avoids the extra nausea. You need a mildly modern CL (can GCL
do this? I think everything else can).
--tim
Greetings!
"Tim Bradshaw" <··········@tfeb.org> writes:
> David Steuber wrote:
> > This code seems to work, but I was wondering whether there was a
> > better way to write it. Also, it seems odd to now go ahead and have
> a
> > form like
> >
> > (setf (getfs foo bar) value)
> >
> > when
> >
> > (setfs foo bar value)
> >
> > does the same thing.
> >
> > What do more experienced Lispers do when they need a function that
> can
> > also be used with SETF? I noticed there is also a long form for
> > DEFSETF which I haven't tried playing with yet. It took me long
> > enough to get SETFS to work when the key didn't exist, ie add a new
> > key value pair.
> >
>
> I haven't really looked at your stuff, but for simple things I use
>
>
> (defun (setf x) (new ...) ...)
>
> which avoids the extra nausea. You need a mildly modern CL (can GCL
> do this? I think everything else can).
>
Yes, GCL 2.7.x (cvs head) has support for setf functions.
Take care,
> --tim
>
--
Camm Maguire ····@enhanced.com
==========================================================================
"The earth is but one country, and mankind its citizens." -- Baha'u'llah
From: Marco Antoniotti
Subject: Re: Writing a getf style function that uses equal
Date:
Message-ID: <qZAdd.1$TY6.43@typhoon.nyu.edu>
Camm Maguire wrote:
> Greetings!
>
> "Tim Bradshaw" <··········@tfeb.org> writes:
>
...
>>I haven't really looked at your stuff, but for simple things I use
>>
>>
>>(defun (setf x) (new ...) ...)
>>
>>which avoids the extra nausea. You need a mildly modern CL (can GCL
>>do this? I think everything else can).
>>
>
>
> Yes, GCL 2.7.x (cvs head) has support for setf functions.
Better late than never. What else is missing?
Cheers
--
Marco
Greetings!
Marco Antoniotti <·······@cs.nyu.edu> writes:
> Camm Maguire wrote:
> > Greetings!
> > "Tim Bradshaw" <··········@tfeb.org> writes:
> >
> ...
> >>I haven't really looked at your stuff, but for simple things I use
> >>
> >>
> >>(defun (setf x) (new ...) ...)
> >>
> >>which avoids the extra nausea. You need a mildly modern CL (can GCL
> >>do this? I think everything else can).
> >>
> > Yes, GCL 2.7.x (cvs head) has support for setf functions.
>
> Better late than never. What else is missing?
>
:-) Not too much actually. Somebody other than me apparently thought
so as well in their cliki post. We are using Paul's test as the
de facto ANSI standard, and this is still somewhat of a moving
target. The bulk of the remaining work at present appears to be in
the pretty printer. We are considering XP.
GCL work goes in bursts like most other open source projects. We had
quite a bit done over the summer. Am hoping another window will open
in the next few months.
It you are interested in volunteering, please speak up :-).
·········@gnu.org.
Take care,
> Cheers
> --
> Marco
>
--
Camm Maguire ····@enhanced.com
==========================================================================
"The earth is but one country, and mankind its citizens." -- Baha'u'llah
Thanks for the update.
I am happy to see progress. And no. I am not volunteering. I had my
share of wandering around EcoLISP pre-ANSI error facilities long time
ago. :)
Cheers
Marco
Camm Maguire wrote:
> Greetings!
>
> Marco Antoniotti <·······@cs.nyu.edu> writes:
>
>
>>Camm Maguire wrote:
>>
>>>Greetings!
>>>"Tim Bradshaw" <··········@tfeb.org> writes:
>>>
>>
>> ...
>>
>>>>I haven't really looked at your stuff, but for simple things I use
>>>>
>>>>
>>>>(defun (setf x) (new ...) ...)
>>>>
>>>>which avoids the extra nausea. You need a mildly modern CL (can GCL
>>>>do this? I think everything else can).
>>>>
>>>
>>>Yes, GCL 2.7.x (cvs head) has support for setf functions.
>>
>>Better late than never. What else is missing?
>>
>
>
> :-) Not too much actually. Somebody other than me apparently thought
> so as well in their cliki post. We are using Paul's test as the
> de facto ANSI standard, and this is still somewhat of a moving
> target. The bulk of the remaining work at present appears to be in
> the pretty printer. We are considering XP.
>
> GCL work goes in bursts like most other open source projects. We had
> quite a bit done over the summer. Am hoping another window will open
> in the next few months.
>
> It you are interested in volunteering, please speak up :-).
> ·········@gnu.org.
>
> Take care,
>
>
>>Cheers
>>--
>>Marco
>>
>
>
From: Kalle Olavi Niemitalo
Subject: Re: Writing a getf style function that uses equal
Date:
Message-ID: <87y8i1yjus.fsf@Astalo.kon.iki.fi>
David Steuber <·····@david-steuber.com> writes:
> It took me long enough to get SETFS to work when the key didn't
> exist, ie add a new key value pair.
It does not work if the property list is initially empty:
(let ((plist '()))
(setf (getfs plist "key") "value")
plist)
;; returns (), should be ("key" "value")
This is because the property list is passed to SETFS by value
and NCONC won't alter the empty list.
In SETF of GETF, the first argument is a place rather than just
a value. You need similar behavior here.
There are several ways to make SETF usable with your functions
or macros:
* macro
: The macro doesn't see the new value; it just expands to a
place.
- You need to ensure the order of evaluation yourself.
+ Supports a variable number of arguments.
+ Supports specially evaluated arguments. (By this I mean
the macro can examine or destructure an argument instead
of causing it to be evaluated as a form. WITH-OPEN-FILE
does that.)
- Supports using arguments as places, but the things you can
do with the places are rather limited.
- Supports multiple stored values, but the things you can
do with the values are rather limited.
+ Would support a variable number of stored values, at least
in principle.
* (setf foo) function
: The new value becomes the first argument.
+ The order of evaluation is automatically correct.
+ Can easily be a generic function.
+ Supports a variable number of arguments.
- Does not support specially evaluated arguments.
- Does not support using arguments as places.
- Does not support multiple stored values.
- Does not support a variable number of stored values.
* short form of DEFSETF
: The new value becomes the last argument.
+ The order of evaluation is automatically correct.
+ Can easily point to a generic function.
+ Supports a variable number of arguments, although you need to
separate the new value from the list yourself.
- Does not support specially evaluated arguments. They may
work with plain SETF, but the setf expansion will have
incorrect temporary variables and value forms, so that
e.g. SHIFTF will fail.
- Does not support using arguments as places. They may work
with plain SETF, but the setf expansion will have incorrect
temporary variables and value forms, so that e.g. SHIFTF will
fail.
- Does not support multiple stored values. They may work with
plain SETF, but the setf expansion will have too few store
variables, so that e.g. SHIFTF will fail.
- Does not support a variable number of stored values.
* long form of DEFSETF
: The new values are put in store variables, whose names will
be told to your code.
+ The order of evaluation is automatically correct.
- There is no shortcut for interfacing with a generic function.
+ Supports a variable number of arguments.
- Does not support specially evaluated arguments.
- Does not support using arguments as places.
+ Supports multiple stored values.
- Does not support a variable number of stored values.
* DEFINE-SETF-EXPANDER
: The new values are put in store variables that your code has
to generate.
- You need to ensure the order of evaluation yourself.
- There is no shortcut for interfacing with a generic function.
+ Supports a variable number of arguments.
+ Supports specially evaluated arguments.
+ Supports using arguments as places.
+ Supports multiple stored values.
- Does not support a variable number of stored values.
I have been using setf functions and DEFINE-SETF-EXPANDER but not
DEFSETF. If I have understood the features of DEFSETF correctly,
the short form of DEFSETF has no advantages over a setf function,
and the long form of DEFSETF is only useful if you are defining a
place where multiple values can be stored.
From: Kalle Olavi Niemitalo
Subject: Re: Writing a getf style function that uses equal
Date:
Message-ID: <87k6tliqfd.fsf@Astalo.kon.iki.fi>
Kalle Olavi Niemitalo <···@iki.fi> writes:
> There are several ways to make SETF usable with your functions
> or macros:
>
> * macro
+ Can be defined locally, with MACROLET.
> * (setf foo) function
+ Can be defined locally, with FLET or LABELS.
> * short form of DEFSETF
- Cannot be defined locally.
> * long form of DEFSETF
- Cannot be defined locally.
> * DEFINE-SETF-EXPANDER
- Cannot be defined locally.
One can almost fake a WITH-SETF-EXPANDER by defining the
access-fn as a local macro that redirects via a global setf
expander; see <http://paste.lisp.org/display/2992#3>. The flaw
in this approach is that (with-setf-expander (foo ...) #'foo) is
then not possible.