-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatomrefs.clj
More file actions
170 lines (143 loc) · 4.39 KB
/
atomrefs.clj
File metadata and controls
170 lines (143 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
(ns atomrefs
(:require [clojure.pprint :as pp])
(:gen-class))
;; === Atoms Example: Game Score System ===
(def game-state
(atom {:player1 {:score 0 :lives 3}
:player2 {:score 0 :lives 3}}))
(defn update-score
"Updates a player's score atomically"
[player points]
(swap! game-state update-in [player :score] + points))
(defn lose-life
"Decrements a player's life atomically"
[player]
(swap! game-state update-in [player :lives] dec))
(defn reset-game
"Resets the game state"
[]
(reset! game-state {:player1 {:score 0 :lives 3}
:player2 {:score 0 :lives 3}}))
;; === Refs Example: Banking System ===
(def checking-account (ref 1000))
(def savings-account (ref 5000))
(defn transfer
"Transfers money between accounts within a transaction"
[from to amount]
(dosync
(when (>= @from amount)
(alter from - amount)
(alter to + amount)
true)))
(defn deposit
"Deposits money into an account"
[account amount]
(dosync
(alter account + amount)))
(defn withdraw
"Withdraws money from an account if sufficient funds"
[account amount]
(dosync
(when (>= @account amount)
(alter account - amount)
true)))
;; === Demonstrating Coordination ===
(def inventory (ref {:apples 10 :oranges 5}))
(def shopping-cart (ref {}))
(defn add-to-cart
"Adds an item to cart if available in inventory"
[item quantity]
(dosync
(when (>= (get @inventory item 0) quantity)
(alter inventory update item - quantity)
(alter shopping-cart update item (fnil + 0) quantity)
true)))
(defn return-item
"Returns an item from cart to inventory"
[item quantity]
(dosync
(when (>= (get @shopping-cart item 0) quantity)
(alter shopping-cart update item - quantity)
(alter inventory update item (fnil + 0) quantity)
true)))
;; === Real-world Scenarios ===
;; 1. Atom for Cache
(def request-cache
(atom {}))
(defn cache-request
"Caches a request result with timestamp"
[key data]
(swap! request-cache assoc key
{:data data
:timestamp (System/currentTimeMillis)}))
(defn get-cached
"Gets cached data if not expired (30 seconds)"
[key]
(when-let [cached (get @request-cache key)]
(when (< (- (System/currentTimeMillis)
(:timestamp cached))
30000)
(:data cached))))
;; 2. Refs for Resource Pool
(def connection-pool
(ref {:available #{:conn1 :conn2 :conn3}
:in-use #{}}))
(defn acquire-connection
"Acquires a connection from the pool"
[]
(dosync
(when-let [conn (first (:available @connection-pool))]
(alter connection-pool
(fn [pool]
(-> pool
(update :available disj conn)
(update :in-use conj conn))))
conn)))
(defn release-connection
"Releases a connection back to the pool"
[conn]
(dosync
(alter connection-pool
(fn [pool]
(-> pool
(update :in-use disj conn)
(update :available conj conn))))))
;; === Examples and Demonstrations ===
(defn run-examples []
(println "\n=== Game Score Example (Atom) ===")
(reset-game)
(update-score :player1 100)
(update-score :player2 50)
(lose-life :player1)
(println "Game State:")
(pp/pprint @game-state)
(println "\n=== Banking Example (Refs) ===")
(println "Initial balances:")
(println "Checking:" @checking-account)
(println "Savings:" @savings-account)
(transfer checking-account savings-account 500)
(println "\nAfter transfer:")
(println "Checking:" @checking-account)
(println "Savings:" @savings-account)
(println "\n=== Shopping Cart Example (Refs) ===")
(dosync (ref-set inventory {:apples 10 :oranges 5}))
(dosync (ref-set shopping-cart {}))
(println "Initial inventory:" @inventory)
(add-to-cart :apples 3)
(add-to-cart :oranges 2)
(println "\nAfter adding to cart:")
(println "Inventory:" @inventory)
(println "Cart:" @shopping-cart)
(return-item :apples 1)
(println "\nAfter returning item:")
(println "Inventory:" @inventory)
(println "Cart:" @shopping-cart)
(println "\n=== Resource Pool Example (Refs) ===")
(let [conn1 (acquire-connection)
conn2 (acquire-connection)]
(println "After acquiring connections:")
(pp/pprint @connection-pool)
(release-connection conn1)
(println "\nAfter releasing connection:")
(pp/pprint @connection-pool)))
(run-examples)