alter

clojure.core

  • (alter ref fun & args)
Must be called in a transaction. Sets the in-transaction-value of
ref to:

(apply fun in-transaction-value-of-ref args)

and returns the in-transaction-value of ref.

1 Example top

  • ;; alter is a way to change the value of a reference.
    
    ;; Here we're defining a ref named 'names' and setting its value to
    ;; an empty vector.
    user=> (def names (ref []))
    #'user/names
    
    ;; A function to add a name to the vector (notice the meat's wrapped
    ;; in a dosync
    user=> (defn add-name [name]
             (dosync
               (alter names conj name)))
    #'user/add-name
    
    user=> (add-name "zack")
    ["zack"]
    
    user=> (add-name "shelley")
    ["zack" "shelley"]
    
    ;; Notice that the var 'names' points to the reference that we created
    user=> (println names)
    #<Ref@658ba380: [zack shelley]>
    
    ;; To get the actual value of the ref, you use the '@' symbol, or deref
    user=> (println @names)
    [zack shelley]
    
    user=> (println (deref names))
    [zack shelley]
Log in to add / edit an example.

See Also top

Log in to add a see also.

Plus_12x12 Minus_12x12 Source clojure/core.clj:2180 top

(defn alter
  "Must be called in a transaction. Sets the in-transaction-value of
  ref to:

  (apply fun in-transaction-value-of-ref args)

  and returns the in-transaction-value of ref."
  {:added "1.0"
   :static true}
  [^clojure.lang.Ref ref fun & args]
    (. ref (alter fun args)))
Vars in clojure.core/alter:
Used in 0 other vars

Comments top

2 comment(s) for alter.

I was fooling around with how exactly ref works with maps. Since the example here uses a vector, I thought maybe some of you might want to see a short example using a map.

In an aggregator I'm working on, I want to keep a record of how many sources and how many articles I've aggregated. Instead of using an atom for each, I'll reference a map called "counts." Here's a simple little function that increments and returns the new value of the counter stored in the map:

 (def counts (ref {:articles 0 :sources 0}))
(defn inc-ref [ref type]
"increment a map value with key type stored in ref"
    (dosync
     (alter ref assoc type (inc (type @ref)))
     (type @ref)))
user> (inc-ref counts :sources)
=>1
user> counts
=>{:articles 0, :sources 1}

and if you wanted to be able to add counters dynamically (one of the advantages of using a map in this context) you could redefine the function employ an optional argument, which if present instructs the function to create a new key-value pair using the name and initial value provided:

(defn inc-ref [ref type & [init-value]]
  (if init-value
    (dosync
     (alter ref assoc type init-value)
     (type @ref))
    (dosync
     (alter ref assoc type (inc (name @ref)))
     (type @ref))))

user> (inc-ref counts :articles)
=>1
user> (inc-ref counts :magazines 1)
=>1
user> (:magazines @counts)
=>1

In the previous example at row 07 has a reference to 'name @ref':

(alter ref assoc type (inc (name @ref)))
maybe is incorrect and the correct mode is:

 (alter ref assoc type (inc (type @ref)))
Log in to add a comment.