setf if

Discussion of Common Lisp

setf if

Postby 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?
User avatar
Kohath
 
Posts: 61
Joined: Mon Jul 07, 2008 8:06 pm
Location: Toowoomba, Queensland, Australia

Re: setf if

Postby 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.
gugamilare
 
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil

Re: setf if

Postby 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.
User avatar
Kohath
 
Posts: 61
Joined: Mon Jul 07, 2008 8:06 pm
Location: Toowoomba, Queensland, Australia


Return to Common Lisp

Who is online

Users browsing this forum: No registered users and 6 guests

cron