http://clojuredocs.org/clojure_core/clojure.core/atom
atom
clojure.core
- (atom x)
- (atom x & options)
Creates and returns an Atom with an initial value of x and zero or
more options (in any order):
:meta metadata-map
:validator validate-fn
If metadata-map is supplied, it will be come the metadata on the
atom. validate-fn must be nil or a side-effect-free fn of one
argument, which will be passed the intended new state on any state
change. If the new state is unacceptable, the validate-fn should
return false or throw an exception.
more options (in any order):
:meta metadata-map
:validator validate-fn
If metadata-map is supplied, it will be come the metadata on the
atom. validate-fn must be nil or a side-effect-free fn of one
argument, which will be passed the intended new state on any state
change. If the new state is unacceptable, the validate-fn should
return false or throw an exception.
1Example top
-
01
user=>
(
def
my-atom
(
atom
0
)
)
02
#'user/my-atom
03
04
user=>
@
my-atom
05
0
06
07
user=>
(
swap!
my-atom
inc
)
08
1
09
10
user=>
@
my-atom
11
1
12
13
user=>
(
swap!
my-atom
(
fn
[
n
]
(
*
(
+
n n
)
2
)
)
)
14
4
swap!
clojure.core
- (swap! atom f)
- (swap! atom f x)
- (swap! atom f x y)
- (swap! atom f x y & args)
Atomically swaps the value of atom to be:
(apply f current-value-of-atom args). Note that f may be called
multiple times, and thus should be free of side effects. Returns
the value that was swapped in.
(apply f current-value-of-atom args). Note that f may be called
multiple times, and thus should be free of side effects. Returns
the value that was swapped in.
-
01
user>
(
def
players
(
atom
(
)
)
)
02
#'user/players
03
04
user>
(
swap!
players
conj
:player1
)
05
(
:player1
)
06
07
user>
(
swap!
players
conj
:player2
)
08
(
:player2
:player1
)
09
10
user>
(
deref
players
)
11
(
:player2
:player1
)
user> (def players (atom ())) #'user/players user> (swap! players conj :player1) (:player1) user> (swap! players conj :player2) (:player2 :player1) user> (deref players) (:player2 :player1)
-
1
user>
(
def
counter
(
atom
0
)
)
2
#'user/counter
3
4
user>
(
swap!
counter
inc
)
5
1
6
7
user>
(
swap!
counter
inc
)
8
2
deref
clojure.core
- (deref ref)
- (deref ref timeout-ms timeout-val)
Also reader macro: @ref/@agent/@var/@atom/@delay/@future/@promise. Within a transaction,
returns the in-transaction-value of ref, else returns the
most-recently-committed value of ref. When applied to a var, agent
or atom, returns its current state. When applied to a delay, forces
it if not already forced. When applied to a future, will block if
computation not complete. When applied to a promise, will block
until a value is delivered. The variant taking a timeout can be
used for blocking references (futures and promises), and will return
timeout-val if the timeout (in milliseconds) is reached before a
value is available. See also - realized?.
returns the in-transaction-value of ref, else returns the
most-recently-committed value of ref. When applied to a var, agent
or atom, returns its current state. When applied to a delay, forces
it if not already forced. When applied to a future, will block if
computation not complete. When applied to a promise, will block
until a value is delivered. The variant taking a timeout can be
used for blocking references (futures and promises), and will return
timeout-val if the timeout (in milliseconds) is reached before a
value is available. See also - realized?.
1Example top
-
01
user=>
(
def
a
(
atom
0
)
)
02
#'user/a
03
user=>
@
a
04
0
05
user=>
(
deref
a
)
06
0
07
08
user=>
(
def
b
(
ref
1
)
)
09
#'user/b
10
user=>
@
b
11
1
12
user=>
(
deref
b
)
13
1
14
15
user=>
(
def
c
(
agent
2
)
)
16
#'user/c
17
user=>
@
c
18
2
19
user=>
(
deref
c
)
20
2
21
22
user=>
(
def
d
(
future
3
)
)
23
#'user/d
24
user=>
@
d
25
3
26
user=>
(
deref
d
)
27
3
future
clojure.core
- (future & body)
Takes a body of expressions and yields a future object that will
invoke the body in another thread, and will cache the result and
return it on all subsequent calls to deref/@. If the computation has
not yet finished, calls to deref/@ will block, unless the variant of
deref with timeout is used. See also - realized?.
invoke the body in another thread, and will cache the result and
return it on all subsequent calls to deref/@. If the computation has
not yet finished, calls to deref/@ will block, unless the variant of
deref with timeout is used. See also - realized?.
2 Examples top
-
01
;; A future's calculation is started here and it runs in another thread
02
user=>
(
def
f
(
future
(
Thread/sleep
10000
)
(
println
"done"
)
100
)
)
03
#'user/f
04
;;if you wait 10 seconds before dereferencing it you'll see "done"
05
06
;; When you dereference it you will block until the result is available.
07
user=>
@
f
08
done
09
100
10
11
;; Dereferencing again will return the already calculated value.
12
=>
@
f
13
100
;; A future's calculation is started here and it runs in another thread user=> (def f (future (Thread/sleep 10000) (println "done") 100)) #'user/f ;;if you wait 10 seconds before dereferencing it you'll see "done" ;; When you dereference it you will block until the result is available. user=> @f done 100 ;; Dereferencing again will return the already calculated value. => @f 100 -
01
;; save the example in a script (e.g. test-future.clj) then run it in the console
02
;;
03
;; > clojure test-future.clj
04
05
(
println
"[Main] calculate the answer to life the universe and everything"
)
06
07
;; Used Thread/sleep to simulate long running process
08
(
def
what-is-the-answer-to-life
(
future
09
(
println
"[Future] started computation"
)
10
(
Thread/sleep
3000
)
;; running for 3 seconds
11
(
println
"[Future] completed computation"
)
12
42
)
)
13
14
(
println
"[Main] created future"
)
15
16
(
Thread/sleep
1000
)
17
(
println
"[Main] do other things while waiting for the answer"
)
18
(
println
"[Main] get the answer"
)
19
(
println
"[Main] the result"
@
what-is-the-answer-to-life
)
20
(
shutdown-agents
)
21
22
23
;; You may get something like this
24
;;
25
;; [Main] calculate the answer to life the universe and everything
26
;; [Future] started computation
27
;; [Main] created future
28
;; [Main] do other things while waiting for the answer
29
;; [Main] get the answer
30
;; [Future] completed computation
31
;; [Main] the result 42
32
33
34
;; Note: If you leave out the call to (shutdown-agents), the program will on
35
;; most (all?) OS/JVM combinations "hang" for 1 minute before the process exits.
36
;; It is simply waiting for background threads, created by the future call, to
37
;; be shut down. shutdown-agents will shut them down immediately, or
38
;; (System/exit <exit-status>) will exit immediately without waiting for them
39
;; to shut down.
40
41
;; This wait occurs even if you use futures indirectly through some other Clojure
42
;; functions that use them internally, such as pmap or clojure.java.shell/sh
43
44
;; http://dev.clojure.org/jira/browse/CLJ-124 is a ticket opened against Clojure,
45
;; as this 1-minute wait is not considered desirable behavior.
agent
clojure.core
- (agent state & options)
Creates and returns an agent with an initial value of state and
zero or more options (in any order):
:meta metadata-map
:validator validate-fn
:error-handler handler-fn
:error-mode mode-keyword
If metadata-map is supplied, it will be come the metadata on the
agent. validate-fn must be nil or a side-effect-free fn of one
argument, which will be passed the intended new state on any state
change. If the new state is unacceptable, the validate-fn should
return false or throw an exception. handler-fn is called if an
action throws an exception or if validate-fn rejects a new state --
see set-error-handler! for details. The mode-keyword may be either
:continue (the default if an error-handler is given) or :fail (the
default if no error-handler is given) -- see set-error-mode! for
details.
zero or more options (in any order):
:meta metadata-map
:validator validate-fn
:error-handler handler-fn
:error-mode mode-keyword
If metadata-map is supplied, it will be come the metadata on the
agent. validate-fn must be nil or a side-effect-free fn of one
argument, which will be passed the intended new state on any state
change. If the new state is unacceptable, the validate-fn should
return false or throw an exception. handler-fn is called if an
action throws an exception or if validate-fn rejects a new state --
see set-error-handler! for details. The mode-keyword may be either
:continue (the default if an error-handler is given) or :fail (the
default if no error-handler is given) -- see set-error-mode! for
details.
1 Example top
-
01
; Agents provide shared access to mutable state. They allow non-blocking (asynchronous as opposed to synchronous atoms) and independent change of individual locations (unlike coordinated change of multiple locations through refs).
02
03
; agent creates one:
04
05
user=>
(
def
counter
(
agent
0
)
)
06
#'user/counter
07
08
; send changes its value:
09
user=>
(
send
counter
inc
)
10
11
; @ or deref provides a snapshot of the current state:
12
user=>
@
counter
13
1
14
15
; agents can reference any data structure:
16
17
user=>
(
def
pulp-fiction
(
agent
{
}
)
)
18
#'user/pulp-fiction
19
user=>
(
send
pulp-fiction
assoc
:act-one
"PROLOGUE"
)
20
user=>
@
pulp-fiction
21
{
:act-one
"PROLOGUE"
}
22
user=>
(
send
pulp-fiction
assoc
:act-two
"VINCENT VEGA & MARSELLUS WALLACE'S WIFE"
)
23
user=>
@
pulp-fiction
24
{
:act-two
"VINCENT VEGA & MARSELLUS WALLACE'S WIFE"
,
:act-one
"PROLOGUE"
}
25
26
; From http://clojure-examples.appspot.com/clojure.core/agent with permission.