tags:

views:

64

answers:

1

Hello, I am having a problem understanding how these functions update the underlying ref, atom etc.

The docs say: (apply f current-value-of-identity args)

(def one (atom 0))
(swap! one inc) ;; => 1

So I am wondering how it got "expanded" to the apply form. It's not mentioned what exactly 'args' in the apply form is. Is it a sequence of arguments or are these separate values?

Was it "expanded" to:

(apply inc 0) ; obviously this wouldnt work, so that leaves only one possibility
(apply inc 0 '())


(swap! one + 1 2 3) ;; #=> 7

Was it:

(apply + 1 1 2 3 '()) ;or
(apply + 1 [1 2 3])

(def two (atom []))
(swap! two conj 10 20) ;; #=> [10 20]

Was it:

(apply conj [] [10 20]) ;or
(apply conj [] 10 20 '())
+4  A: 

The passage you quoted from swap!'s docstring means that what happens is the equivalent of swapping in a new value for the Atom obtained from the old one with (apply f old-value args), where args is a seq of all additional arguments passed to swap!.

What actually happens is different, but that's just an implementation detail. For the sake of curiosity: Atoms have a Java method called swap, which is overloaded to take from one to four arguments. The first one is always an IFn (the f passed to swap!); the second and third, in present, are the first two extra arguments to that IFn; the fourth, if present, is an ISeq of extra arguments beyond the first two. apply is never involved and the fixed arity cases don't even call the IFn's applyTo method (they just use invoke). This improves performance in the common case where not too many extra arguments are passed to swap!.

Michał Marczyk