Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (ns bank.account
- (:require
- [clojure.spec.alpha :as s]))
- (s/def ::fname string?)
- (s/def ::lname string?)
- (s/def ::cents integer?)
- ;; It's currently valid to have a negative balance.
- ;; Could alternatively do something like (s/and ::cents (complement neg?))
- (s/def ::balance ::cents)
- ;; maybe use an inst here?
- (s/def ::date-of-birth string?)
- ;; The first name is optional, the others are required.
- (s/def ::account
- (s/keys :req [::lname ::balance ::date-of-birth]
- :opt [::fname]))
- (s/fdef deposit
- :args (s/cat :account ::account, :quantity ::cents)
- :ret ::account)
- ;; This is the implementation I would use regardless of whether I used spec or not.
- (defn deposit [account quantity]
- (update account ::balance + quantity))
- (s/fdef withdraw-valid?
- :args (s/cat :account ::account, :quantity ::cents)
- :ret boolean?)
- (defn withdraw-valid? [{::keys [balance] :as account} quantity]
- (>= balance quantity))
- (s/fdef withdraw
- :args (s/cat :account ::account, :quantity ::cents)
- :ret ::account)
- (defn withdraw [account quantity]
- (update account ::balance - quantity))
- (comment
- ;; Usage
- (def me #::{:lname "madstap"
- :balance 100
- :date-of-birth "01-01-17"})
- (withdraw me 100) ;=> #:bank.account{,,, :balance 0 ,,,}
- (deposit me 1000) ;=> ;=> #:bank.account{,,, :balance 1100 ,,,}
- (withdraw-valid? me 1000) ;=> false
- ;; Bonus: Generate random, valid bank accounts.
- ;; NB: Needs test.check as a dependency [org.clojure/test.check "0.10.0-alpha2"]
- (clojure.pprint/pprint (s/exercise ::account))
- ([#:bank.account{:lname "", :balance -1, :date-of-birth "", :fname ""}
- #:bank.account{:lname "", :balance -1, :date-of-birth "", :fname ""}]
- [#:bank.account{:lname "", :balance 0, :date-of-birth "6", :fname ""}
- #:bank.account{:lname "", :balance 0, :date-of-birth "6", :fname ""}]
- ,,,)
- )
Add Comment
Please, Sign In to add comment