davypough
davypough

Reputation: 1941

Simplifying complex setf expressions

For rapid prototyping purposes in common-lisp it would be convenient to be able to easily function-modify an object in an arbitrary data structure. This would seem to involve calling an arbitrary function on a place in the data structure, replacing the object at that place with the result of the function call. Common-lisp has a number of specialized modification macros (eg, incf, push, getf, etc) for particular types of objects, and setf for generalized place modification (eg, setf-second, setf-aref, setf-gethash, etc). But rather than inventing new specialized macros for other object types, or having to mentally consider the characteristics of each macro (slowing down development), it might be nice to have a generalized setf-like modification capability that was simpler to use than setf. For example, instead of (setf (second (getf plist indicator)) (1+ (second (getf plist indicator)))) or (incf (second (getf plist indicator))), one might write (callf (second (getf plist indicator)) #'1+), using any of the normal one argument functions (or lambda-expression) provided by common-lisp or the user. Here is an attempt at code:

(defun call (object function) (funcall function object))
(define-modify-macro callf (&rest args) call)

Will something like this work for all general cases, and can it actually simplify code in practice?

Upvotes: 1

Views: 104

Answers (1)

sds
sds

Reputation: 60004

callf

I think what you are looking for is _f from OnLisp 12.4:

(defmacro _f (op place &rest args)
  "Modify place using `op`, e.g., (incf a) == (_f a 1+)"
  (multiple-value-bind (vars forms var set access)
      (get-setf-expansion place)
    `(let* (,@(mapcar #'list vars forms)
            (,(car var) (,op ,access ,@args)))
       ,set)))

This uses get-setf-expansion - the workhorse of generalized reference handling.

Note that _f only works with single-value places. IOW, (_f (values a b c) 1+) will not increment all 3 variables. It is not all that hard to fix that though...

can it actually simplify code in practice?

This really depends on your coding style and the specific problem you are solving.

Upvotes: 2

Related Questions