Skip to content

Instantly share code, notes, and snippets.

@nathanmarz
Created June 24, 2015 17:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nathanmarz/7a6bbf80770d2a232f33 to your computer and use it in GitHub Desktop.
Save nathanmarz/7a6bbf80770d2a232f33 to your computer and use it in GitHub Desktop.
Practical example of Specter
(def world
{:people [{:money 129827 :name "Alice Brown"}
{:money 100 :name "John Smith"}
{:money 6821212339 :name "Donald Trump"}
{:money 2870 :name "Charlie Johnson"}
{:money 8273821 :name "Charlie Rose"}
]
:bank {:funds 4782328748273}}
)
(defn transfer
"Note that this function works on *any* world structure. This handles
arbitrary many to many transfers of a fixed amount without overdrawing anyone"
[world from-path to-path amt]
(let [givers (select from-path world)
receivers (select to-path world)
total-receive (* amt (count givers))
total-give (* amt (count receivers))]
(if (every? #(>= % total-give) givers)
(->> world
(update from-path #(- % total-give))
(update to-path #(+ % total-receive))
)
(throw (IllegalArgumentException.
"Insufficient funds"))
)))
(defn pay-fee [world]
(transfer world
[:people ALL :money]
[:bank :funds]
1)
)
(defn bank-give-dollar [world]
(transfer world
[:bank :funds]
[:people ALL :money]
1)
)
(defn pay-poor-fee [world]
(transfer world
[:people ALL :money #(< % 3000)]
[:bank :funds]
50)
)
(defn rich-people [world]
(select [:people
ALL
(selected? :money #(>= % 1000000000))
:name]
world))
(defn user [name]
(comp-paths :people
ALL
(selected? :name
#(= % name))))
(defn transfer-users [world from to amt]
(transfer world
[(user from) :money]
[(user to) :money]
amt))
(defn bank-loyal-bonus
"Bank gives $5000 to earliest three users"
[world]
(transfer world
[:bank :funds]
[:people (srange 0 3) ALL :money]
5000))
(defn add-person [world person]
(setval [:people END]
[person]
world)
)
(defn bank-recent-charity-bonus
"Bank gives $1000 to most recent person with less than 5000 dollars"
[world]
(transfer world
[:bank :funds]
[:people
(filterer [:money #(< % 5000)])
(selected? (view empty?) not)
LAST
:money]
1000))
(defn mark-wealth-status [world]
(setval [:people
ALL
(if-path [:money #(>= % 100000)]
:rich
:not-so-rich)]
true
world))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment