Last active
November 22, 2017 16:44
-
-
Save madstap/ae2ced5f049d73c27e138bbf6bf07b64 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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 ""}] | |
,,,) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment