-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchannels.clj
88 lines (72 loc) · 2.78 KB
/
channels.clj
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
(ns state-examples.channels
(:require [clojure.core.async :as async]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Utility & Convenience Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- make-call
([acc-ch cmd]
(make-call acc-ch cmd nil))
([acc-ch cmd amount]
(let [client-ch (async/chan)]
(async/>!! acc-ch {:client client-ch :cmd cmd :amount amount})
(when-let [msg (async/<!! client-ch)]
(:result msg)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Private, Message-passing Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- send-name [data client]
(async/>!! client {:result (:name data)})
data)
(defn- send-balance [data client]
(async/>!! client {:result (:balance data)})
data)
(defn- send-apply-interest [data client]
(let [balance (:balance data)
interest-rate (:interest-rate data)]
(async/>!! client {:result :ok})
(assoc data :balance (+ balance (* balance interest-rate)))))
(defn- send-withdrawl [data client amt]
(if (<= amt (:balance data))
(do
(async/>!! client {:result :ok})
(assoc data :balance (- (:balance data) amt)))
(do
(async/>!! client {:result :insufficient-funds})
data)))
(defn- send-deposit [data client amt]
(async/>!! client {:result :ok})
(assoc data :balance (+ (:balance data) amt)))
(defn- dispatch-send
([data client cmd]
(dispatch-send data client cmd nil))
([data client cmd amount]
(case cmd
:name (send-name data client)
:balance (send-balance data client)
:apply-interest (send-apply-interest data client)
:withdraw (send-withdrawl data client amount)
:deposit (send-deposit data client amount))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; API ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn new-account [name balance interest-rate]
(let [ch (async/chan)
data {:name name
:balance balance
:interest-rate interest-rate}]
(async/go
(loop [d data]
(when-let [msg (async/<! ch)]
(recur (dispatch-send
d (:client msg) (:cmd msg) (:amount msg))))))
ch))
(defn get-name [acc-ch]
(make-call acc-ch :name))
(defn get-balance [acc-ch]
(make-call acc-ch :balance))
(defn apply-interest [acc-ch]
(make-call acc-ch :apply-interest))
(defn withdraw [acc-ch amount]
(make-call acc-ch :withdraw amount))
(defn deposit [acc-ch amount]
(make-call acc-ch :deposit amount))