From: David Steuber
Subject: Writing a getf style function that uses equal
Date: 
Message-ID: <876556oxvb.fsf@david-steuber.com>
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

From: Tim Bradshaw
Subject: Re: Writing a getf style function that uses equal
Date: 
Message-ID: <1098270532.700781.150440@z14g2000cwz.googlegroups.com>
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
From: Camm Maguire
Subject: Re: Writing a getf style function that uses equal
Date: 
Message-ID: <54ekjt8oxz.fsf@intech19.enhanced.com>
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
From: Camm Maguire
Subject: Re: Writing a getf style function that uses equal
Date: 
Message-ID: <54r7nq7817.fsf@intech19.enhanced.com>
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
From: Marco Antoniotti
Subject: Re: Writing a getf style function that uses equal
Date: 
Message-ID: <eKwed.12$TY6.5241@typhoon.nyu.edu>
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.