That's an important rule to remember when the definition of a DSP/VUG requires branching.

A performance-time variable is expanded/updated the first time within the body of a definition. With the trivial example

(with-samples ((s (blabla-is-performance-time ...)))
  s s s s s)

the generated performance-time function is

(progn (setf s (blabla-is-performance-time ...))
       s s s s)

The next example

(if (> s 0.5) up-depends-on-s down-depends-on-s)

works without surprises and the result is

(if (> (setf s (blabla-...)) 0.5)
    up-depends-on-s
    down-depends-on-s)

but often the generated performance-time function in

(if rain-p s (* s 0.5))

is not what we want because the result is

(if rain-p
    (setf s (blabla-is-performance-time ...))
    (* s 0.5))

and S is performance-time only if it's raining.

We have at least two solutions:

  1. MAYBE-EXPAND before IF

    (maybe-expand s)
    (if rain-p s (* s 0.5))

    result:

    (setf s (blabla-is-performance-time ...))
    (if rain-p s (* s 0.5))
  2. UPDATE

    (if rain-p s (* (update s) 0.5))

    result:

    (labels ((set-s[gensym-ed] ()
               (setf s (blabla-is-performance-time ...))))
      ...
      (if rain-p
          (set-s[gensym-ed])
          (* (set-s[gensym-ed]) 0.5)))

Sourceforge project page