setf if

Discussion of Common Lisp
Post Reply
Kohath
Posts: 61
Joined: Mon Jul 07, 2008 8:06 pm
Location: Toowoomba, Queensland, Australia
Contact:

setf if

Post by Kohath » Sun Aug 29, 2010 4:51 am

I thought up this:

Code: Select all

(define-setf-expander if (test then &optional else)
  "Lets you use IF as the place of a setf form.
For example (setf (if test a b) 7).  In the example,
a will be set to 7 if test returns true, otherwise
b will be set to 7.
The then and (optional) else forms must be places."
  (let ((new-value (gensym)))
    (values ()
            ()
            `(,new-value)
            `(if ,test (setf ,then ,new-value)
                       ,(if else `(setf ,else ,new-value) new-value))
            `(if ,test ,then ,@(when else `(,else))))))
It's easier to read at Lisp Paste here.

It lets you write:

Code: Select all

(setf (if <test> <place-a> <place-b>) <new-value-form>)
instead of:

Code: Select all

(if <test>
  (setf <place-a> <new-value-form>)
  (setf <place-b> <new-value-form>))
and having to introduce a temporary variable if you don't want to evaluate <new-value-form> twice. It will simplify some of the code I will be writing.

Here's an example of the power of this feature of CL - the setf expansion being used by pop (it can also be used by incf, decf, etc.):

Code: Select all

(let ((a (list 1 2 3)) (b (list 4 5 6)))
  (print (pop (if (zerop (random 2)) a b)))
  (list a b))
Has anyone done this before, or got any caveats, advice, or comments?

gugamilare
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil
Contact:

Re: setf if

Post by gugamilare » Sun Aug 29, 2010 8:39 am

Your code looks nice and useful. However, I don't know if this plays well on all implementations. For instance, I know that SBCL complains (with a continuable error) about any attempt to define something on the standard symbols (it complains about anything potentially unportable). Maybe you would be safer defining a macro IF-SETF.

Kohath
Posts: 61
Joined: Mon Jul 07, 2008 8:06 pm
Location: Toowoomba, Queensland, Australia
Contact:

Re: setf if

Post by Kohath » Sun Aug 29, 2010 5:50 pm

Ah, thanks for commenting - here are my findings (on WinXP):
  • Corman CL 3.0: not already defined, works fine, no problems.
  • Clozure CL 1.5: not already defined, works fine, no problems.
  • CLISP 2.47: already defined, causes continuable package lock error.
  • SBCL 1.0.37: not already defined, causes continuable package lock error.
The CLISP doc page on the COMMON-LISP package lock was informative, and I thought the link to a USENET post was quite useful too.

Post Reply