-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.html
419 lines (324 loc) · 12.7 KB
/
index.html
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Clojure backshop</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="railscast.css">
</head>
<body>
<div class="wrapper">
<nav id="sidebar">
<div class="sidebar-header">
<h3>Clojure Backshop</h3>
</div>
<ul id="menu" class="list-unstyled components">
<li>
<a href="#lein">lein</a>
</li>
<li>
<a href="#repl">repl</a>
</li>
<li>
<a href="#def">def</a>
</li>
<li>
<a href="#defn">defn - λ - anonymous</a>
</li>
<li>
<a href="#namespace">namespace</a>
</li>
<li>
<a href="#if-else">if - else</a>
</li>
<li>
<a href="#">let</a>
</li>
<li>
<a href="#">map</a>
</li>
<li>
<a href="#">partial</a>
</li>
<li>
<a href="#">reduce</a>
</li>
<li>
<a href="#">comp</a>
</li>
<li>
<a href="#">-></a>
</li>
<li>
<a href="#">ring</a>
</li>
<li>
<a href="#">middleware</a>
</li>
<li>
<a href="#">test</a>
</li>
</ul>
</nav>
<div id="content" style="width: 100%">
<div id="lein" class="hide clj">
<h2>leinigen</h2>
<p> declarative configuration and project automation made simple </p>
<div class="line"></div>
<pre>
<code class="hljs bash">
# install leinigen
$ brew install leinigen
# creating new app
$ lein new app backshop
# running tests
$ lein test
# start a repl
$ lein repl
# all commands
$ lein
</code>
</pre>
</div>
<div id="repl" class="hide clj">
<h2>repl</h2>
<p> read-evaluate-print-loop will empower your development experience </p>
<div class="line"></div>
<pre>
<code class="hljs clojure">
$ lein repl
;; you can type all clojure commands and get the feedback immediately
backshop.core=> (+ 1 2)
3
backshop.core=> (defn sum [a b] (+ a b))
#'backshop.core/sum
backshop.core=> (sum 1 2)
3
</code>
</pre>
<p> better exception experience on repl
add the follow to project.clj </p>
<pre>
<code class="hljs clojure">
:repl-options { :caught clj-stacktrace.repl/pst+ }
:profiles {:dev { :dependencies [[clj-stacktrace "0.2.8"]]} }
</code>
</pre>
<p> the above settings will print better stacktrace once things blows up. </p>
<pre>
<code class="hljs clojure">
backshop.core=> (/ 1 0)
ArithmeticException Divide by zero clojure.lang.Numbers.divide (Numbers.java:158)
java.lang.ArithmeticException: Divide by zero
Numbers.java:158 clojure.lang.Numbers.divide
Numbers.java:3808 clojure.lang.Numbers.divide
form-init5807277563015766183.clj:1 backshop.core/eval1376
form-init5807277563015766183.clj:1 backshop.core/eval1376
Compiler.java:6927 clojure.lang.Compiler.eval
Compiler.java:6890 clojure.lang.Compiler.eval
core.clj:3105 clojure.core/eval
core.clj:3101 clojure.core/eval
main.clj:240 clojure.main/repl[fn]
main.clj:240 clojure.main/repl[fn]
main.clj:258 clojure.main/repl[fn]
main.clj:258 clojure.main/repl
main.clj:174 clojure.main/repl
RestFn.java:1523 clojure.lang.RestFn.invoke
interruptible_eval.clj:87 clojure.tools.nrepl.middleware.interruptible-eval/evaluate[fn]
AFn.java:152 clojure.lang.AFn.applyToHelper
AFn.java:144 clojure.lang.AFn.applyTo
core.clj:646 clojure.core/apply
core.clj:1881 clojure.core/with-bindings*
core.clj:1881 clojure.core/with-bindings*
RestFn.java:425 clojure.lang.RestFn.invoke
interruptible_eval.clj:85 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj:55 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj:222 clojure.tools.nrepl.middleware.interruptible-eval/interruptible-eval[fn]
interruptible_eval.clj:190 clojure.tools.nrepl.middleware.interruptible-eval/run-next[fn]
AFn.java:22 clojure.lang.AFn.run
ThreadPoolExecutor.java:1142 java.util.concurrent.ThreadPoolExecutor.runWorker
ThreadPoolExecutor.java:617 java.util.concurrent.ThreadPoolExecutor$Worker.run
Thread.java:745 java.lang.Thread.run
</code>
</pre>
</div>
<div id="def" class="hide clj">
<h2>"variables"</h2>
<p> bind values to names -> 'variables' </p>
<div class="line"></div>
<pre>
<code class="hljs clojure">
;; the way to bind values to name is using def
backshop.core=> (def workshop-name "backshop")
;;now you can use the name workshop-name everywhere
backshop.core=> workshop-name
"backshop"
;;you could even bind functions to name
backshop.core=> (def super-sum (fn [a b] (+ a b)))
backshop.core=> (super-sum 1 2)
3
;; you will see in the next section that you could use defn to define function as well
;;defn is the same as (def name (fn []))
;; you could bind whatever value to any symbol
backshop.core=> (def persons [{:name "john"} {:name "doe"}])
backshop.core=> persons
[{:name "john"} {:name "doe"}]
</code>
</pre>
</div>
<div id="defn" class="hide clj">
<h2>functions</h2>
<p> functions are first class citizens </p>
<div class="line"></div>
<h4> tldr; </h4>
<p> you could create functions using defn or simply using fn </p>
<pre>
<code class="hljs clojure">
;; the easy way to create a function is with fn
user=> (fn [a b] (+ a b))
;; let's bind a name to the function
user=> (def my-super-sum (fn [a b] (+ a b) ))
;; now you can easily apply arguments to the function
user=> (my-super-sum 1 4) ; 5
;; DEFN
;; simpler way to create my-super-sum would be using defn
user=> (defn my-super-sum [a b] (+ a b))
;; RETURN
;; the last form expression evaluated will be the return's function
user=> (defn my-crazy-sum [a b]
(println "logging +" a b)
(+ a b))
;; as functions are value, we could return a function
user=> (defn sum-factory [a]
(fn [b] (+ a b)))
user=> (def inc-five (sum-factory 5))
user=> (inc-five 10) ; will return 15
;; we could create 'anonymous' functions in clojure with special syntax
user=> (def sum #(+ %1 %2))
;; the #(function %1 %2 ... %n) syntax is a easy way to create inline func
;; and very useful specially on map/reduce
; shorthand for (fn [a] (inc a)) => #(inc %1)
user=> (map #(inc %1) [1 2 3 4])
</code>
</pre>
</div>
<div id="namespace" class="hide clj">
<h2>namespace</h2>
<p> your clojure runtime it is nothing than a set of namespaces talking with each other</p>
<p> namespaces are global entities that you can always refer by using the FQDN</p>
<p> for instance: (<string>clojure.core/inc</strong> 1) </p>
<div class="line"></div>
<pre>
<code class="hljs clojure">
(create-ns 'webshop) ;; will create the namespace
(in-ns 'webshop) ;; update the current *ns* to webshop
;; try to sum two Numbers
(+ 10 5) ; Unable to resolve symbol: + in this context
;; we need somehow refer the clojure.core namespace
;; clojure.core namespace contains the core clojure functions
;; webshop namespace contains none symbol
;; will import all public symbols to current namespace
(clojure.core/refer 'clojure.core)
;; selective import
(clojure.core/refer 'clojure.core :only '[+])
;; as an alternative to copying the mappings from clojure.core namespace
;; you can create an alias
(alias 'core 'clojure.core)
;; then you can refer clojure.core as core
(core/+ 1 2)
;; what about load a cloJAR into our namespace
;; first let's add on our project.clj the dependency to cheshire
;; [cheshire "5.8.0"]
;; https://github.com/dakrone/cheshire
(require '[cheshire.core :as c])
(c/generate-string {:name "backshop"})
(c/generate-smile {:foo "bar" :baz 5})
;; now we have the base to use the ns macro function
;; ns is a shorthand to refer and alias
(ns webshop.core
(:require [cheshire.core :as c]))
;; or
(ns webshop.core
(:require [cheshire.core :refer :all]))
;; or
(ns webshop.core
(:require [cheshire.core :refer [generate-smile generate-string]]))
</optgroup>
</code>
</pre>
</div>
<div id="if-else" class="hide clj">
<h2>if-else</h2>
<p> some people will say if-else are useless </p>
<div class="line"></div>
<pre>
<code class="hljs clojure">
;; if has a peculiar syntax
(if (condition) (truthy form expression) (falsy form expression))
(if true "true" "false") ;; will return "true"
;; in clojure everything is truthy except nil and false
(if nil "true" "false") ;; will return "false"
(def person {:age 17 :name "thiago" :})
(if (> (:age person) 18)
(beer :drink)
(go-home :netflix))
(if (not (> (:age person) 18))
(go-home :nextflix)
(beer :drink))
(if-not (> (:age person) 18)
(go-home :netflix)
(beer :drink))
;; wait, we can only execute one form expression
;; what if I need to execute more than one form in case of truthy/falsy value
;; "do" for the rescue
(do
(println "hello")
(+ 1 2))
;; do function will receive N number of expressions and return the last one
(if (has-credit? transaction)
(do
(account/withdraw transaction)
(email/send :withdraw)))
;; remember, nil and false are the falsy values in clojure
;; everything else will be considered truthy
(if-let [person (api/fetch-by-id 192)]
(account/notify person)
(log/warn "person does not exists"))
</code>
</pre>
</div>
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/languages/clojure.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/languages/bash.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.2.0/highlightjs-line-numbers.min.js"></script>
<script type="text/javascript">
hljs.initHighlightingOnLoad();
hljs.initLineNumbersOnLoad();
$(document).ready(function () {
render(window.location.hash || "#lein");
$("#menu").on("click", "a", function() {
render($(this).attr("href"));
});
function render(page) {
hide();
show(page)
}
function hide() {
$("#menu li").removeClass('active');
$("#content .clj").addClass('hide');
}
function show(page) {
$(page).toggleClass('hide');
$("a[href='" + page + "']").each(function(i) {
$(this).parent().toggleClass('active')
});
}
});
</script>
</body>
</html>