Using get-setf-expansion
First things first, you should know about the order of evaluation in modifying forms:


  (operator preceding-form* place following-form*)
  
  The evaluation of each such form proceeds like this:
  
  
  Evaluate each of the preceding-forms, in left-to-right order.
  Evaluate the subforms of the place, in the order specified by the second value of the setf expansion for that place.
  Evaluate each of the following-forms, in left-to-right order.
  Read the old value from place.
  Compute the new value.
  Store the new value into place.
  


I'll take your idea with these changes:


Instead of !, I'll call it updatef
Instead of @, I'll use an identifying form, (:place &lt;place&gt;), where &lt;place&gt; is the actual place
Instead of splashing the form (e.g. (updatef delete 2 (:place *x*))), I'll make it a single destructuring argument of the macro (e.g. (updatef (delete 2 (:place *x*))))


I'm aware that this syntax is more verbose, but due to the specific nature of updatef's behavior, I think it shouldn't be used just about anywhere.

(defmacro updatef ((&amp;whole form function &amp;rest args) &amp;environment env)
  (flet ((is-place-form (arg)
           (and (consp arg)
                (eq (card arg) :place)
                (consp (cdr arg)))))
    (let ((place-rest (member-if #'is-place-form args)))
      (assert (not (null place-rest)) ()
              "No place form in updatef.")
      (assert (null (member-if #'is-place-form (rest place-rest))) ()
              "More than one place form in updatef.")
      (let* ((preceding-forms (ldiff args place-rest))
             (place (second (first place-rest)))
             (following-forms (rest place-rest))
             (preceding-vars (loop for preceding-form in preceding-forms collect (gensym "preceding-var")))
             (following-vars (loop for following-form in following-forms collect (gensym "following-var"))))
        (multiple-value-bind (vars vals store-vars writer-form reader-form)
            (get-setf-expansion place env)
          (assert (= (length vars) (length vals)) ()
                  "Place expansion has different amount of variables than initializing forms in updatef.")
          `(let* (,@(mapcar #'(lambda (var form)
                                `(,var ,form))
                            (append preceding-vars vars following-vars)
                            (append preceding-forms vals following-forms)))
             (multiple-value-bind (,@store-vars)
                 (,function ,@preceding-vars ,reader-form ,@following-vars)
               ,writer-form)))))))


One of the good things that this macro does is to evaluate the subforms only once.  However, it doesn't help with certain kinds of places where it would be useful to operate atomically, such as setf of gethash or implementation specific atomic operations on places.



Here's a more permissive version that allows certain errors from setf expansions, namely: more or less vars than vals and a writer-form that doesn't return the new value(s).

Also, I made it so it does nothing special (regarding setf behavior) in case no form is (:place &lt;place&gt;), and to use the first such form in case there are more than one.

(defmacro updatef ((&amp;whole form function &amp;rest args) &amp;environment env)
  (flet ((is-place-form (arg)
           (and (consp arg)
                (eq (card arg) :place)
                (consp (cdr arg)))))
    (let ((place-rest (member-if #'is-place-form args)))
      (cond ((null place-rest)
             (warn "No place form in updatef, no update generated.")
             form)
            (t
             (when (not (null (member-if #'is-place-form (rest place-rest))))
               (warn "More than one place form in updatef, first place will be used."))
             (let* ((preceding-forms (ldiff args place-rest))
                    (place (second (first place-rest)))
                    (following-forms (rest place-rest))
                    (preceding-vars (loop for preceding-form in preceding-forms collect (gensym "preceding-var")))
                    (following-vars (loop for following-form in following-forms collect (gensym "following-var"))))
               (multiple-value-bind (vars vals store-vars writer-form reader-form)
                   (get-setf-expansion place env)
                 (when (not (= (length vars) (length vals)))
                   (warn "Place expansion has different amount of variables than initializing forms in updatef."))
                 `(let* (,@(mapcar #'(lambda (var form)
                                       `(,var ,form))
                                   preceding-vars preceding-forms)
                         ,@(mapcar #'(lambda (var form)
                                       `(,var ,form))
                                   vars vals)
                         ;; In case there are more vars than vals
                         ,@(nthcdr (length vals) vars))
                    ;; In case there are more vals than vars
                    ,@(nthcdr (length vars) vals)
                    (let* (,@(mapcar #'(lambda (var form)
                                         `(,var ,form))
                                     following-vars following-forms))
                      (multiple-value-bind (,@store-vars)
                          (,function ,@preceding-vars ,reader-form ,@following-vars)
                        ,writer-form
                        ;; In case writer-form doesn't return the new value(s)
                        (values ,@store-vars)))))))))))


I'm sure that if you try, you can find many more places where to check for errors and warnings, and decide if you're permissive about them or not.  It has been quite a while since I've played with places myself.