;;;; update, ++ and -- evaluate every subexpression of their place once, as ;;;; C's compound assignment does. `calls` counts the index function: one call ;;;; per form, and the read and the write land on the same element. (defonce calls i32 0) (defn next-index [] i32 (set calls (+ calls 1)) (- calls 1)) (defstruct Body [velocity i32 hits [3 i32]]) (defn add [x i32 y i32] i32 (+ x y)) (defclass counter [n i32]) (defn which-slot [] dyn (set calls (+ calls 1)) :n) (defn main [] i32 (let [xs [10 20 30] v (vec-new i32) g (Body {.velocity 5})] (push v 1) (push v 2) (push v 3) ;; next-index answers 0, then 1, then 2. (++ (at xs (next-index))) (-- (at v (next-index))) (update (at xs (next-index)) * 3) (println calls) ; 3 (println (at xs 0) (at xs 1) (at xs 2)) ; 11 20 90 (println (at v 0) (at v 1) (at v 2)) ; 1 1 3 ;; A field, with a macro as the function, and with arguments after it. (update (.velocity g) inc) (update (.velocity g) add 10) (println (.velocity g)) ; 16 ;; A path through a field into an element: the struct is written in place, ;; not in a copy. (set calls 0) (update (at (.hits g) (next-index)) + 7) (++ (at (.hits g) (next-index))) (println calls) ; 2 (println (at (.hits g) 0) (at (.hits g) 1)) ; 7 1 ;; Through a pointer. (let [p (addr (.velocity g))] (update (deref p) * 2) (println (.velocity g))) ; 32 (free v)) ;; A class slot, with the key computed once. (let [c (counter 4)] (set calls 0) (++ (get c (which-slot))) (update (get c (which-slot)) * 10) (println calls (get c :n))) ; 2 50 0)