Paweł Kapała
public class HelloWorld {
private static HelloWorld instance;
public static void main (String[] args) {
instantiateHelloWorldMainClassAndRun();
}
public static void instantiateHelloWorldMainClassAndRun() {
instance = new HelloWorld();
}
public HelloWorld() {
HelloWorldFactory factory = HelloWorldFactory.getInstance();
IHelloWorld helloWorld = factory.createHelloWorld();
IHelloWorldString helloWorldString = helloWorld.getHelloWorld();
IPrintStrategy printStrategy = helloWorld.getPrintStrategy();
IStatusCode code = helloWorld.print(printStrategy, helloWorldString);
if (code.getStatusCode() != 0) {
throw new RuntimeException("Failed to print: " + code.getStatusCode());
}
}
}https://gist.github.com/lolzballs/2152bc0f31ee0286b722
http://66.media.tumblr.com/30ba33358b951e56ae23d85bab7c16f1/tumblr_inline_o8opm7EDEX1raprkq_500.gif
elegant code that represent domain
java libs
jvm tools / DEV OPS
functional
community
mature
In the beginning there
was only chaos, then
out of the void...
0.2
2/3
2
5302542730
"Wawel"
"Kraków"
"hello world"
"John"
"Mścigniew"
:title
:id
:chupacabra
:name
("a" "b" "c" "d" "e" "f")
(0 1 2 3 4 5 6 7)
(:a :b :c :d :e)
()
[0 1 2 3 4 5 6]
["John" "Jane" "Lucy"]
[:title :name :id]
{:id 1 :name "John" :surname "Doe"}
{:subject "this" :predicate "is"
:preposition "a" :object "map"}
a-symbol
bar
namespace/example
iamfoo
(str "a" "b" "c")
(conj [] 1 2 3 4)
(+ 2 4 6 7)
(first [1 2 3 4])
(assoc {:id 1 :name "John"} :surname "Doe")
(= {:id 1 :name "Joe"} {:id 1 :name "Joe"})
(defn greeter [arg1 arg2]
(str "Hello " arg1 " " arg2 "!"))
(defn plus [arg1 arg2]
(+ arg1 arg2))
#(+ %1 %2)
#(str "Hello " %1 " " %2 "!")
*at least for the most part
{:name "Krakus" :health 100}(defn citizen [name]
{:name name :health 100})
(citizen "Krakus"){:name "Krakus" :health 100 :title :king}(defn promote [citizen title]
(assoc citizen :title title))
(defn king [name]
(promote (citizen name) :king))
(king "Krakus")
assoc returns new map with key value added to it
{:name "Wawel"}(defn castle [name]
{:name name})
(castle "Wawel"){:name "Wawel" :citizens [
{:name "Krakus" :title "King"}]}(defn occupy [what whom]
(update what :citizens
(fnil conj []) whom))
(occupy (castle "Wawel") (king "Krakus"))
update returns map with a specified key changed by given function
conj returns collection with element appended
fnil executes specified function passing argument in case of nil
{:energy 10 :size 10}(defn food [energy]
{:energy energy :size 10})
(defn ram[] (food 10))
(defn cow[] (food 20))
(ram){:name "Wawel" :goods [{:energy 10 :size 10}]}(defn store [structure food]
(update structure :goods
(fnil conj []) food))
(store (castle "Wawel") (ram))({:energy 20 :size 10}
{:energy 20 :size 10}
{:energy 20 :size 10}
;... 15 more
{:energy 20 :size 10}
{:energy 20 :size 10})(repeatedly 20 cow)repeatadly returns (lazy) collection containing function result times the number specified, or infinite if size is not specified
(defn knight [name]
(assoc
(promote (citizen name) :knight)
:power 100))
(knight "Małowuj"){:name "Małowuj" :title :knight :power 100}{:name "Wawel" :citizens [
{:name "Małowuj" :title :knight :power 100}
{:name "Minigniew" :title :knight :power 100}
{:name "Gromisław" :title :knight :power 100}
{:name "Nowosiodł" :title :knight :power 100}
{:name "Twardomir" :title :knight :power 100}
{:name "Włościobyt" :title :knight :power 100}]}(reduce occupy (castle "Wawel")
(map knight ["Małowuj" "Minigniew" "Gromisław"
"Nowosiodł" "Twardomir" "Włościobyt"]))
map executes function for each collection element and returns a collection of results
reduce calls two-arg function on a first element of the collection, then passes the return back to the function as a first argument and takes next element of the collection...
(defn dragon [name]
{:name name :health 1000 :power 1000})
(dargon "Smok"){:name "Smok" :health 1000 :power 1000}(occupy (castle "Wawel") (dragon "Smok")){:name "Wawel" :citizens [{:name "Smok"
:health 1000 :power 1000}](defn eat [who what]
(merge-with + who what))
(eat (dragon "Smok") (ram)){:name "Smok" :health 1000 :power 1000
:energy 10 :size 10}merge-with combines two map into one using provided function (+ in this case) on the values of matching keys
(defn attack [target who]
(update target :health
(fnil - 0) (:power who 0)))
(attack (dragon "Smok") (knight "Minigniew"))
{:name "Smok" :health 900 :power 1000}; {:name "Minigniew" :health -900
; :title :knight :power 100}
true(defn dead? [who]
(<= (:health who 0) 0))
(dead?
(attack (knight "Minigniew") (dragon "Smok")))(defn sulfur []
{:thirst 500})
(defn tar []
{:size 500))
(defn ram-with-sulfur-and-tar []
(merge-with + (ram) (sulfur) (tar)))
(ram-with-sulfur-and-tar){:energy 10 :size 510 :thirst 500}(eat (dragon "Smok")
(ram-with-sulfur-and-tar))
{:name "Smok" :health 1000 :power 1000
:energy 10 :size 510 :thirst 500}(defn water []
{:thirst -1 :size 10})
(defn vistula []
(repeatedly water))
(take 100 (vistula))({:thirst -1 :size 10}
{:thirst -1 :size 10}
{:thirst -1 :size 10}
{:thirst -1 :size 10}
;... 96x more
)({:name "Smok-0" :health -1000 :power 1000}
{:name "Smok-1" :health -1000 :power 1000}
{:name "Smok-2" :health -1000 :power 1000}
{:name "Smok-3" :health -1000 :power 1000}
;... 96x more
)(defn pieceof [who no]
(-> who
(update :name str "-" no)
(assoc :health -1000)))
(map #(pieceof (dragon "Smok") %1) (range 100))-> Is called "a threading macro" that passes result of previous function call as first parameter to next call in block, the above is equivalent to:
(assoc (update who :name str "-" no) :health -1000)
(defn story []
[#(occupy % king "Krakus")
#(occupy % knight "Małowuj" "Minigniew"
"Gromisław" "Nowosiodł" "Twardomir" "Włościobyt")
#(produce-all % (repeatedly 20 cow))
#(produce-all % (repeatedly 50 ram))
#(occupy % dragon "Smok")
#(consume-all %)
#(attack-some % "Smok" "Małowuj" "Minigniew"
"Gromisław" "Nowosiodł" "Twardomir" "Włościobyt")
#(attack-back % "Smok" "Małowuj" "Minigniew"
"Gromisław" "Nowosiodł" "Twardomir" "Włościobyt")
#(collect-dead %)
#(occupy % cobbler "Skuba")
#(consume-all %)
#(produce % (ram-with-sulfur-and-tar))
#(consume-all %)
#(produce-all % (take 100 (vistula)))
#(consume-all %)
#(blow-to-pieces % "Smok")])(defn story-line[n]
(reduce #(%2 %1)
(castle "Wawel")
(take n (story))))
(story-line 5){:name "Wawel"
:citizens [
{:name "Krakus" :health 100 :title :king
:energy 100 :size 50}
{:name "Smok" :health 400 :power 1000
:energy 40 :size 40}]
:goods [
{:energy 20 :size 10}
{:energy 20 :size 10}
{:energy 20 :size 10}
{:energy 20 :size 10}
{:energy 20 :size 10}]}GET /story/1
{"name": "Wawel"}GET /story/2
{"name": "Wawel", "inhabitants": [
{"name": "Krakus", "title": "king"}]}(def app
(api swagger-meta
(context "/api" [] :tags ["api"]
(GET "/story/:line" [line]
:summary "story by line"
(ok (story/story-line
(Integer/parseInt line)))))))https://github.com/kapware/clj-krakus/
4clojure.com
Clojure for the Brave and True
clojure.org
Structure and interpretation of computer programs
Mastering Clojure
clojurekoans.com