├── LICENSE
├── README.md
└── clojure-basics
├── .gitignore
├── README.md
├── learn_clojure
├── basics.clj
└── basics_simple.clj
├── project.clj
└── src
└── basics
├── exercise1.clj
└── welcome.clj
/LICENSE:
--------------------------------------------------------------------------------
1 | Attribution 4.0 International
2 |
3 | =======================================================================
4 |
5 | Creative Commons Corporation ("Creative Commons") is not a law firm and
6 | does not provide legal services or legal advice. Distribution of
7 | Creative Commons public licenses does not create a lawyer-client or
8 | other relationship. Creative Commons makes its licenses and related
9 | information available on an "as-is" basis. Creative Commons gives no
10 | warranties regarding its licenses, any material licensed under their
11 | terms and conditions, or any related information. Creative Commons
12 | disclaims all liability for damages resulting from their use to the
13 | fullest extent possible.
14 |
15 | Using Creative Commons Public Licenses
16 |
17 | Creative Commons public licenses provide a standard set of terms and
18 | conditions that creators and other rights holders may use to share
19 | original works of authorship and other material subject to copyright
20 | and certain other rights specified in the public license below. The
21 | following considerations are for informational purposes only, are not
22 | exhaustive, and do not form part of our licenses.
23 |
24 | Considerations for licensors: Our public licenses are
25 | intended for use by those authorized to give the public
26 | permission to use material in ways otherwise restricted by
27 | copyright and certain other rights. Our licenses are
28 | irrevocable. Licensors should read and understand the terms
29 | and conditions of the license they choose before applying it.
30 | Licensors should also secure all rights necessary before
31 | applying our licenses so that the public can reuse the
32 | material as expected. Licensors should clearly mark any
33 | material not subject to the license. This includes other CC-
34 | licensed material, or material used under an exception or
35 | limitation to copyright. More considerations for licensors:
36 | wiki.creativecommons.org/Considerations_for_licensors
37 |
38 | Considerations for the public: By using one of our public
39 | licenses, a licensor grants the public permission to use the
40 | licensed material under specified terms and conditions. If
41 | the licensor's permission is not necessary for any reason--for
42 | example, because of any applicable exception or limitation to
43 | copyright--then that use is not regulated by the license. Our
44 | licenses grant only permissions under copyright and certain
45 | other rights that a licensor has authority to grant. Use of
46 | the licensed material may still be restricted for other
47 | reasons, including because others have copyright or other
48 | rights in the material. A licensor may make special requests,
49 | such as asking that all changes be marked or described.
50 | Although not required by our licenses, you are encouraged to
51 | respect those requests where reasonable. More_considerations
52 | for the public:
53 | wiki.creativecommons.org/Considerations_for_licensees
54 |
55 | =======================================================================
56 |
57 | Creative Commons Attribution 4.0 International Public License
58 |
59 | By exercising the Licensed Rights (defined below), You accept and agree
60 | to be bound by the terms and conditions of this Creative Commons
61 | Attribution 4.0 International Public License ("Public License"). To the
62 | extent this Public License may be interpreted as a contract, You are
63 | granted the Licensed Rights in consideration of Your acceptance of
64 | these terms and conditions, and the Licensor grants You such rights in
65 | consideration of benefits the Licensor receives from making the
66 | Licensed Material available under these terms and conditions.
67 |
68 |
69 | Section 1 -- Definitions.
70 |
71 | a. Adapted Material means material subject to Copyright and Similar
72 | Rights that is derived from or based upon the Licensed Material
73 | and in which the Licensed Material is translated, altered,
74 | arranged, transformed, or otherwise modified in a manner requiring
75 | permission under the Copyright and Similar Rights held by the
76 | Licensor. For purposes of this Public License, where the Licensed
77 | Material is a musical work, performance, or sound recording,
78 | Adapted Material is always produced where the Licensed Material is
79 | synched in timed relation with a moving image.
80 |
81 | b. Adapter's License means the license You apply to Your Copyright
82 | and Similar Rights in Your contributions to Adapted Material in
83 | accordance with the terms and conditions of this Public License.
84 |
85 | c. Copyright and Similar Rights means copyright and/or similar rights
86 | closely related to copyright including, without limitation,
87 | performance, broadcast, sound recording, and Sui Generis Database
88 | Rights, without regard to how the rights are labeled or
89 | categorized. For purposes of this Public License, the rights
90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar
91 | Rights.
92 |
93 | d. Effective Technological Measures means those measures that, in the
94 | absence of proper authority, may not be circumvented under laws
95 | fulfilling obligations under Article 11 of the WIPO Copyright
96 | Treaty adopted on December 20, 1996, and/or similar international
97 | agreements.
98 |
99 | e. Exceptions and Limitations means fair use, fair dealing, and/or
100 | any other exception or limitation to Copyright and Similar Rights
101 | that applies to Your use of the Licensed Material.
102 |
103 | f. Licensed Material means the artistic or literary work, database,
104 | or other material to which the Licensor applied this Public
105 | License.
106 |
107 | g. Licensed Rights means the rights granted to You subject to the
108 | terms and conditions of this Public License, which are limited to
109 | all Copyright and Similar Rights that apply to Your use of the
110 | Licensed Material and that the Licensor has authority to license.
111 |
112 | h. Licensor means the individual(s) or entity(ies) granting rights
113 | under this Public License.
114 |
115 | i. Share means to provide material to the public by any means or
116 | process that requires permission under the Licensed Rights, such
117 | as reproduction, public display, public performance, distribution,
118 | dissemination, communication, or importation, and to make material
119 | available to the public including in ways that members of the
120 | public may access the material from a place and at a time
121 | individually chosen by them.
122 |
123 | j. Sui Generis Database Rights means rights other than copyright
124 | resulting from Directive 96/9/EC of the European Parliament and of
125 | the Council of 11 March 1996 on the legal protection of databases,
126 | as amended and/or succeeded, as well as other essentially
127 | equivalent rights anywhere in the world.
128 |
129 | k. You means the individual or entity exercising the Licensed Rights
130 | under this Public License. Your has a corresponding meaning.
131 |
132 |
133 | Section 2 -- Scope.
134 |
135 | a. License grant.
136 |
137 | 1. Subject to the terms and conditions of this Public License,
138 | the Licensor hereby grants You a worldwide, royalty-free,
139 | non-sublicensable, non-exclusive, irrevocable license to
140 | exercise the Licensed Rights in the Licensed Material to:
141 |
142 | a. reproduce and Share the Licensed Material, in whole or
143 | in part; and
144 |
145 | b. produce, reproduce, and Share Adapted Material.
146 |
147 | 2. Exceptions and Limitations. For the avoidance of doubt, where
148 | Exceptions and Limitations apply to Your use, this Public
149 | License does not apply, and You do not need to comply with
150 | its terms and conditions.
151 |
152 | 3. Term. The term of this Public License is specified in Section
153 | 6(a).
154 |
155 | 4. Media and formats; technical modifications allowed. The
156 | Licensor authorizes You to exercise the Licensed Rights in
157 | all media and formats whether now known or hereafter created,
158 | and to make technical modifications necessary to do so. The
159 | Licensor waives and/or agrees not to assert any right or
160 | authority to forbid You from making technical modifications
161 | necessary to exercise the Licensed Rights, including
162 | technical modifications necessary to circumvent Effective
163 | Technological Measures. For purposes of this Public License,
164 | simply making modifications authorized by this Section 2(a)
165 | (4) never produces Adapted Material.
166 |
167 | 5. Downstream recipients.
168 |
169 | a. Offer from the Licensor -- Licensed Material. Every
170 | recipient of the Licensed Material automatically
171 | receives an offer from the Licensor to exercise the
172 | Licensed Rights under the terms and conditions of this
173 | Public License.
174 |
175 | b. No downstream restrictions. You may not offer or impose
176 | any additional or different terms or conditions on, or
177 | apply any Effective Technological Measures to, the
178 | Licensed Material if doing so restricts exercise of the
179 | Licensed Rights by any recipient of the Licensed
180 | Material.
181 |
182 | 6. No endorsement. Nothing in this Public License constitutes or
183 | may be construed as permission to assert or imply that You
184 | are, or that Your use of the Licensed Material is, connected
185 | with, or sponsored, endorsed, or granted official status by,
186 | the Licensor or others designated to receive attribution as
187 | provided in Section 3(a)(1)(A)(i).
188 |
189 | b. Other rights.
190 |
191 | 1. Moral rights, such as the right of integrity, are not
192 | licensed under this Public License, nor are publicity,
193 | privacy, and/or other similar personality rights; however, to
194 | the extent possible, the Licensor waives and/or agrees not to
195 | assert any such rights held by the Licensor to the limited
196 | extent necessary to allow You to exercise the Licensed
197 | Rights, but not otherwise.
198 |
199 | 2. Patent and trademark rights are not licensed under this
200 | Public License.
201 |
202 | 3. To the extent possible, the Licensor waives any right to
203 | collect royalties from You for the exercise of the Licensed
204 | Rights, whether directly or through a collecting society
205 | under any voluntary or waivable statutory or compulsory
206 | licensing scheme. In all other cases the Licensor expressly
207 | reserves any right to collect such royalties.
208 |
209 |
210 | Section 3 -- License Conditions.
211 |
212 | Your exercise of the Licensed Rights is expressly made subject to the
213 | following conditions.
214 |
215 | a. Attribution.
216 |
217 | 1. If You Share the Licensed Material (including in modified
218 | form), You must:
219 |
220 | a. retain the following if it is supplied by the Licensor
221 | with the Licensed Material:
222 |
223 | i. identification of the creator(s) of the Licensed
224 | Material and any others designated to receive
225 | attribution, in any reasonable manner requested by
226 | the Licensor (including by pseudonym if
227 | designated);
228 |
229 | ii. a copyright notice;
230 |
231 | iii. a notice that refers to this Public License;
232 |
233 | iv. a notice that refers to the disclaimer of
234 | warranties;
235 |
236 | v. a URI or hyperlink to the Licensed Material to the
237 | extent reasonably practicable;
238 |
239 | b. indicate if You modified the Licensed Material and
240 | retain an indication of any previous modifications; and
241 |
242 | c. indicate the Licensed Material is licensed under this
243 | Public License, and include the text of, or the URI or
244 | hyperlink to, this Public License.
245 |
246 | 2. You may satisfy the conditions in Section 3(a)(1) in any
247 | reasonable manner based on the medium, means, and context in
248 | which You Share the Licensed Material. For example, it may be
249 | reasonable to satisfy the conditions by providing a URI or
250 | hyperlink to a resource that includes the required
251 | information.
252 |
253 | 3. If requested by the Licensor, You must remove any of the
254 | information required by Section 3(a)(1)(A) to the extent
255 | reasonably practicable.
256 |
257 | 4. If You Share Adapted Material You produce, the Adapter's
258 | License You apply must not prevent recipients of the Adapted
259 | Material from complying with this Public License.
260 |
261 |
262 | Section 4 -- Sui Generis Database Rights.
263 |
264 | Where the Licensed Rights include Sui Generis Database Rights that
265 | apply to Your use of the Licensed Material:
266 |
267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right
268 | to extract, reuse, reproduce, and Share all or a substantial
269 | portion of the contents of the database;
270 |
271 | b. if You include all or a substantial portion of the database
272 | contents in a database in which You have Sui Generis Database
273 | Rights, then the database in which You have Sui Generis Database
274 | Rights (but not its individual contents) is Adapted Material; and
275 |
276 | c. You must comply with the conditions in Section 3(a) if You Share
277 | all or a substantial portion of the contents of the database.
278 |
279 | For the avoidance of doubt, this Section 4 supplements and does not
280 | replace Your obligations under this Public License where the Licensed
281 | Rights include other Copyright and Similar Rights.
282 |
283 |
284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability.
285 |
286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
296 |
297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
306 |
307 | c. The disclaimer of warranties and limitation of liability provided
308 | above shall be interpreted in a manner that, to the extent
309 | possible, most closely approximates an absolute disclaimer and
310 | waiver of all liability.
311 |
312 |
313 | Section 6 -- Term and Termination.
314 |
315 | a. This Public License applies for the term of the Copyright and
316 | Similar Rights licensed here. However, if You fail to comply with
317 | this Public License, then Your rights under this Public License
318 | terminate automatically.
319 |
320 | b. Where Your right to use the Licensed Material has terminated under
321 | Section 6(a), it reinstates:
322 |
323 | 1. automatically as of the date the violation is cured, provided
324 | it is cured within 30 days of Your discovery of the
325 | violation; or
326 |
327 | 2. upon express reinstatement by the Licensor.
328 |
329 | For the avoidance of doubt, this Section 6(b) does not affect any
330 | right the Licensor may have to seek remedies for Your violations
331 | of this Public License.
332 |
333 | c. For the avoidance of doubt, the Licensor may also offer the
334 | Licensed Material under separate terms or conditions or stop
335 | distributing the Licensed Material at any time; however, doing so
336 | will not terminate this Public License.
337 |
338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
339 | License.
340 |
341 |
342 | Section 7 -- Other Terms and Conditions.
343 |
344 | a. The Licensor shall not be bound by any additional or different
345 | terms or conditions communicated by You unless expressly agreed.
346 |
347 | b. Any arrangements, understandings, or agreements regarding the
348 | Licensed Material not stated herein are separate from and
349 | independent of the terms and conditions of this Public License.
350 |
351 |
352 | Section 8 -- Interpretation.
353 |
354 | a. For the avoidance of doubt, this Public License does not, and
355 | shall not be interpreted to, reduce, limit, restrict, or impose
356 | conditions on any use of the Licensed Material that could lawfully
357 | be made without permission under this Public License.
358 |
359 | b. To the extent possible, if any provision of this Public License is
360 | deemed unenforceable, it shall be automatically reformed to the
361 | minimum extent necessary to make it enforceable. If the provision
362 | cannot be reformed, it shall be severed from this Public License
363 | without affecting the enforceability of the remaining terms and
364 | conditions.
365 |
366 | c. No term or condition of this Public License will be waived and no
367 | failure to comply consented to unless expressly agreed to by the
368 | Licensor.
369 |
370 | d. Nothing in this Public License constitutes or may be interpreted
371 | as a limitation upon, or waiver of, any privileges and immunities
372 | that apply to the Licensor or You, including from the legal
373 | processes of any jurisdiction or authority.
374 |
375 |
376 | =======================================================================
377 |
378 | Creative Commons is not a party to its public
379 | licenses. Notwithstanding, Creative Commons may elect to apply one of
380 | its public licenses to material it publishes and in those instances
381 | will be considered the “Licensor.” The text of the Creative Commons
382 | public licenses is dedicated to the public domain under the CC0 Public
383 | Domain Dedication. Except for the limited purpose of indicating that
384 | material is shared under a Creative Commons public license or as
385 | otherwise permitted by the Creative Commons policies published at
386 | creativecommons.org/policies, Creative Commons does not authorize the
387 | use of the trademark "Creative Commons" or any other trademark or logo
388 | of Creative Commons without its prior written consent including,
389 | without limitation, in connection with any unauthorized modifications
390 | to any of its public licenses or any other arrangements,
391 | understandings, or agreements concerning use of licensed material. For
392 | the avoidance of doubt, this paragraph does not form part of the
393 | public licenses.
394 |
395 | Creative Commons may be contacted at creativecommons.org.
396 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Learn Clojure
2 |
3 | Curriculum for an introductory course to Clojure.
4 |
5 | ```
6 | Welcome to
7 | ~~~ Introduction to Clojure programming ~~~
8 |
9 | .okko.
10 | lMMWMMMx
11 | ;N:. ;XMo
12 | x, 0W.
13 | .Wk
14 | xM.
15 | .XMk
16 | KMMM.
17 | .KMMWMd
18 | .XMMW,kW.
19 | KMMM: 'Mo
20 | 0MMMc 0N
21 | 0MMMl ;Md
22 | 0MMMl KM; .d
23 | 0MMMd ,MWo. '0d
24 | 0MMMk :WMMMMMK.
25 | 'llll .:dxd;
26 |
27 | Bruno Bonacci
28 | ```
29 |
30 | ## Author & contributors
31 |
32 | * Bruno Bonacci
33 | * Dayo Oliyide
34 |
35 | ## Setup
36 |
37 | If you don't have a development environment already set up
38 | please follow the instructions at the [following page](https://github.com/ClojureBridge/curriculum/blob/gh-pages/outline/setup.md).
39 |
40 | Alternative Clojure IDEs
41 |
42 | * Relatively simple ones
43 | * LightTable (http://lighttable.com/)
44 | * NightCode (https://sekao.net/nightcode/)
45 | * Cursive (https://cursive-ide.com/)
46 | * VSCode (Calva extension) (https://calva.io/)
47 | * More complex ones
48 | * Emacs + Cider (https://github.com/clojure-emacs/cider)
49 | * Preludex (Emacs + Cider) (https://github.com/BrunoBonacci/preludex)
50 | * Spacemacs + Cider (Better vim) (http://spacemacs.org/)
51 | * Vim + Fireplace (https://github.com/ctford/vim-fireplace-easy)
52 |
53 | If you have already your environment ready to go, then choose your learning path below.
54 |
55 | ## Courses
56 |
57 | * [Clojure basics](/clojure-basics)
58 |
59 |
60 | ## Learn more
61 |
62 | * Books
63 | * "The Joy of Clojure" (http://www.amazon.com/dp/1617291412/)
64 | * "Clojure Programming" (http://www.amazon.com/dp/1449394701/)
65 | * "Clojure For the Brave and True" (http://www.amazon.com/dp/1593275919/)
66 | * "Living Clojure" (http://www.amazon.com/dp/1491909048/)
67 | * more Clojure's books: http://clojure.org/community/books
68 | * Online resources
69 | * "Clojure For the Brave and True" (http://www.braveclojure.com/clojure-for-the-brave-and-true/)
70 | * "Clojure from the ground up" (https://aphyr.com/tags/Clojure-from-the-ground-up)
71 | * Katas
72 | * "4 Clojure" (http://www.4clojure.com/) **MUST**
73 | * "Codewars" (http://www.codewars.com/)
74 |
75 |
76 | ## Getting help
77 |
78 | Post a question to the mailing list or use the slack channel.
79 |
80 | * All London's events: http://www.londonclojurians.org/
81 | * Mailing list: https://groups.google.com/forum/#!forum/london-clojurians
82 | * Slack channel: http://clojurians.net/
83 | * IRC channel #Clojure on Freenode (http://irc.lc/freenode/clojure/irctc)
84 |
85 | ## License
86 |
87 |  This material is distributed under [Creative Commons Attribution 4.0 International Public License](http://creativecommons.org/licenses/by/4.0/legalcode)
88 |
--------------------------------------------------------------------------------
/clojure-basics/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /classes
3 | /checkouts
4 | pom.xml
5 | pom.xml.asc
6 | *.jar
7 | *.class
8 | /.lein-*
9 | /.nrepl-port
10 | .hgignore
11 | .hg/
12 |
--------------------------------------------------------------------------------
/clojure-basics/README.md:
--------------------------------------------------------------------------------
1 | # learn-clojure
2 |
3 | ## Clojure Basics
4 |
5 | This project contains code and documentation for a introductory
6 | Clojure course.
7 |
8 | The following sections are described:
9 |
10 | * The REPL
11 | * Clojure syntax and the function call
12 | * Boolean values and `nil`
13 | * Logical truth
14 | * Numbers
15 | * Integer values
16 | * Decimals values
17 | * Floating point
18 | * BigDecimal
19 | * Rationals values
20 | * Characters
21 | * Strings
22 | * Keywords
23 | * Collections
24 | * Lists
25 | * Vectors
26 | * Maps
27 | * Sets
28 | * The sequence abstraction
29 | * Regular expression patterns
30 | * Symbols and Vars
31 | * Immutability
32 | * Functions
33 | * Purity
34 | * Function definition
35 | * Function with multi-arities
36 | * high-order functions
37 | * Anonymous functions or lambda functions
38 | * Closures
39 | * Recursion
40 | * Function composition and partial functions
41 | * Vars, namespaces, scope, and local bindings
42 | * Destructuring (blog post)
43 | * Flow control
44 | * if
45 | * not, and, or
46 | * when
47 | * cond
48 | * case
49 | * Core functions
50 | * apply
51 | * map
52 | * reduce
53 | * filter
54 | * sort
55 | * group-by
56 | * frequencies
57 | * partition
58 | * into
59 | * Operations with files
60 | * slurp
61 | * spit
62 | * Error handling
63 | * Macros (blog post)
64 |
65 | ## Getting started
66 |
67 | Start your IDE of choice and open the file `src/basics/welcome.clj`
68 | and evaluate the expression.
69 |
70 | Then open `learn_clojure/basics.clj` and read through
71 | the description.
72 |
--------------------------------------------------------------------------------
/clojure-basics/learn_clojure/basics.clj:
--------------------------------------------------------------------------------
1 | (ns learn-clojure.basics
2 | (:require [clojure.string :as str]))
3 |
4 | ;; Welcome to
5 | ;; ~~~ Introduction to Clojure programming ~~~
6 | ;;
7 | ;; .okko.
8 | ;; lMMWMMMx
9 | ;; ;N:. ;XMo
10 | ;; x, 0W.
11 | ;; .Wk
12 | ;; xM.
13 | ;; .XMk
14 | ;; KMMM.
15 | ;; .KMMWMd
16 | ;; .XMMW,kW.
17 | ;; KMMM: 'Mo
18 | ;; 0MMMc 0N
19 | ;; 0MMMl ;Md
20 | ;; 0MMMl KM; .d
21 | ;; 0MMMd ,MWo. '0d
22 | ;; 0MMMk :WMMMMMK.
23 | ;; 'llll .:dxd;
24 | ;;
25 | ;; Bruno Bonacci
26 | ;;
27 | ;; ## Clojure basics
28 | ;;
29 | ;; I will try to introduce concepts gradually
30 | ;; without assuming prior knowledge of Clojure (or
31 | ;; any other LISP dialect). However I will assume
32 | ;; that you are already an experienced developer
33 | ;; in any other popular language such as Java,
34 | ;; C/C++, Python or Javascript. General
35 | ;; programming concepts such as functions,
36 | ;; parameters, recursion, objects and common
37 | ;; data-structures such as: linked lists, maps (or
38 | ;; dictionaries), vectors and sets will be assumed
39 | ;; to be already known.
40 | ;;
41 | ;;
42 | ;; ### The REPL
43 | ;;
44 | ;; The REPL is (IMHO) one of the key Clojure
45 | ;; features. REPL stands for: __Read Eval Print
46 | ;; Loop__ and although this is present in many
47 | ;; languages such as python, ruby and soon Java as
48 | ;; well, in Clojure it is part of the main
49 | ;; development workflow. In other words if you are
50 | ;; not using the REPL for your Clojure development
51 | ;; you are doing it wrong!
52 | ;;
53 | ;; The REPL allows you to connect to a running
54 | ;; system, inspect runtime values, and even make
55 | ;; live changes in your code without having to
56 | ;; restart your system.
57 | ;;
58 | ;; It is the best way to explore a system or a
59 | ;; dataset and get familiar with its domain.
60 | ;;
61 | ;; In terms of feedback, the Read Eval Print Loop
62 | ;; is so much better than TDD, that a new
63 | ;; development methodology has been created/inspired..
64 | ;; the **REPL Driven Development**
65 | ;;
66 | ;; For this session we are going to use the REPL
67 | ;; to explore Clojure features, this might give a
68 | ;; glimpse of what is possible to do with the
69 | ;; Clojure REPL.
70 | ;;
71 | ;;
72 | ;; ### Clojure syntax
73 | ;;
74 | ;; Clojure syntax is very simple.
75 | ;; A program is composed of s-expressions,
76 | ;; every s-expr is delimited by a set of
77 | ;; parenthesis. Line comments are made
78 | ;; with a semicolon (`;`) and by conventions
79 | ;; a full line comment is two or more consecutive
80 | ;; semicolons `;;` while and in-line comment
81 | ;; is only one `;`.
82 | ;;
83 | ;; You can skip the evaluation and execution of a
84 | ;; block with the `comment` form, however this
85 | ;; isn't a complete comment in the same way as the
86 | ;; semicolon, as it still get parsed by the reader
87 | ;; in the same way as the rest of the
88 | ;; code. Therefore the comment block has to be
89 | ;; valid Clojure code. For example:
90 | ;;
91 | ;; ;; this is a valid comment
92 | ;; ;; a : b : c
93 | ;; ;; while this won't be readable
94 | ;; (comment a : b : c)
95 | ;;
96 | ;; The difference is that the semicolon comment is
97 | ;; ignored by the reader, while the `comment`
98 | ;; block is something that you could have
99 | ;; implemented yourself using the macros, which in
100 | ;; this case just tells the compiler to not
101 | ;; generate anything any code.
102 | ;;
103 | ;; We will denote the output of the REPL evaluation
104 | ;; with by prefixing the result with `;;=>`.
105 | ;; So every time you see a Clojure expression
106 | ;; followed by `;;=>` and a value it means
107 | ;; that the value is the result of the evaluation
108 | ;; of last expression.
109 | ;;
110 | ;; ### The function call.
111 | ;;
112 | ;; The first concept I will introduce is how to
113 | ;; make a function call. We will see more about
114 | ;; functions later, but for the moment I want to
115 | ;; make sure that you will understand the next few
116 | ;; examples. Let's start to make some comparisons
117 | ;; with method or function calls in a few
118 | ;; different languages
119 | ;;
120 | ;; // java and C++
121 | ;; myObject.myFunction(arg1, arg2, arg3);
122 | ;;
123 | ;; // C
124 | ;; myFunction(myStruct, arg1, arg2, arg3);
125 | ;;
126 | ;; ;; Clojure
127 | ;; (my-function myObject arg1 arg2 arg3)
128 | ;;
129 | ;;
130 | ;; As you can see in Clojure the brackets surround
131 | ;; the function and all its arguments. In object
132 | ;; oriented languages such as Java and C++ the
133 | ;; object comes before the method name or function
134 | ;; name. In C and Clojure the function comes
135 | ;; first, then followed by the target
136 | ;; object. Let's see a concrete example, _for the
137 | ;; sake of the example I will omit the required
138 | ;; package imports._
139 | ;;
140 | ;;
141 | ;; // java
142 | ;; "Hello World!".toLowerCase();
143 | ;;
144 | ;; // C - single char
145 | ;; tolower(*c);
146 | ;; // C - Whole string
147 | ;; for ( ; *c; ++c) *c = tolower(*c);
148 | ;; ^^^^^^^^^^^^^
149 | ;;
150 | ;; ;; Clojure
151 | ;; (lower-case "Hello World!")
152 | ;;
153 | ;;
154 | ;; _NOTE: In the standard C library there is only
155 | ;; a function to turn a single character into its
156 | ;; lowercase form, that's why there is a loop._
157 | ;;
158 | ;; However in the `tolower(*c)` we can see the
159 | ;; function comes first followed by its arguments
160 | ;; surrounded by bracket. In Clojure, the
161 | ;; expression (called `s-expr`) starts with an
162 | ;; open bracket, followed by a function followed
163 | ;; by a list of arguments.
164 | ;;
165 | ;; The following code is designed to run in the
166 | ;; Clojure REPL, the conventions I will follow
167 | ;; throughout the text is to display the result of
168 | ;; the expression evaluation prefixed with this
169 | ;; evaluation marker `;;=>`. So every time you'll
170 | ;; see a Clojure expression followed by `;;=>` and
171 | ;; followed by another value it means that the
172 | ;; result of the evaluation of the prior
173 | ;; expression is what follows the marker. For
174 | ;; example the evaluation of the expression `(+ 1
175 | ;; 1)` with its result will be noted as follow:
176 | ;;
177 | ;; (+ 1 1)
178 | ;; ;;=> 2
179 | ;;
180 | ;; ### Booleans
181 | ;;
182 | ;; In Clojure we have boolean values like in many
183 | ;; other languages. No surprise here we have two
184 | ;; values `true` and `false` which just evaluate
185 | ;; to themselves. Now we can use the function
186 | ;; `type` to see what is the concrete type of
187 | ;; these values in the host platform, and if we
188 | ;; check the type of these values we'll find that
189 | ;; they are just simple Java `java.lang.Boolean`
190 | ;; objects.
191 | ;;
192 |
193 | true
194 | ;;=> true
195 |
196 | false
197 | ;;=> false
198 |
199 | (type true)
200 | ;;=> java.lang.Boolean
201 |
202 | ;;
203 | ;; Now boolean values are often associated to
204 | ;; **logic programming** and the concept of
205 | ;; **"truthiness"**. In strongly typed languages
206 | ;; such as Java you can only use boolean in
207 | ;; conditional operation. Some other languages
208 | ;; such C/C++ have a more loose definition
209 | ;; **"truthiness"**. __In Clojure everything is
210 | ;; considered **true** with the exception of
211 | ;; `false` and `nil`.__
212 | ;;
213 | ;; For example we can use the following form `(if
214 | ;; condition truthy falsey)` which evaluates the
215 | ;; given `condition` and if the condition has a
216 | ;; logical value of true then it will evaluate
217 | ;; `truthy` form otherwise it evaluates the
218 | ;; `falsey`.
219 | ;;
220 |
221 | (if true "it's true" "it's false")
222 | ;;=> "it's true"
223 |
224 | (if false "it's true" "it's false")
225 | ;;=> "it's false"
226 |
227 | (if nil "it's true" "it's false")
228 | ;;=> "it's false"
229 |
230 | (if "HELLO" "it's true" "it's false")
231 | ;;=> "it's true"
232 |
233 | (if 1 "it's true" "it's false")
234 | ;;=> "it's true"
235 |
236 | ;;
237 | ;; ### Numbers
238 | ;;
239 | ;; Clojure has a quite unique support for
240 | ;; numerical values. As you would expect every
241 | ;; number just evaluates to itself.
242 | ;;
243 | ;; #### Integers
244 | ;;
245 | ;; They are mapped to `java.lang.Long`, but since
246 | ;; they can be indefinitely large they can be
247 | ;; promoted to `clojure.lang.BigInt` once they go
248 | ;; beyond the `java.lang.Long#MAX_VALUE`.
249 | ;;
250 |
251 | 1 ;;=> 1
252 | -4 ;;=> -4
253 |
254 | 9223372036854775807 ; java.lang.Long#MAX_VALUE
255 | ;;=> 9223372036854775807
256 |
257 | (type 1)
258 | ;;=> java.lang.Long
259 |
260 | (type 9223372036854775807)
261 | ;;=> java.lang.Long
262 |
263 | 29384756298374652983746528376529837456
264 | ;;=> 29384756298374652983746528376529837456N
265 |
266 | (type 29384756298374652983746528376529837456)
267 | ;;=> clojure.lang.BigInt
268 |
269 | (type 1N)
270 | ;;=> clojure.lang.BigInt
271 |
272 | ;;
273 | ;; You can also define integers literals in other basis
274 | ;; such as octal, hexadecimals and binary.
275 | ;;
276 |
277 | 127 ;;=> 127 ; decimal
278 | 0x7F ;;=> 127 ; hexadecimal
279 | 0177 ;;=> 127 ; octal
280 | 32r3V ;;=> 127 ; base 32
281 | 2r01111111 ;;=> 127 ; binary
282 | 36r3J ;;=> 127 ; base 36
283 |
284 | 36rClojure ;;=> 27432414842
285 | 2r0111001101010001001001 ;;=> 1889353
286 |
287 | ;;
288 | ;; In Clojure there are no operators, in fact `+`,
289 | ;; `-`, `*` and `/` are normal functions.
290 | ;;
291 |
292 | (+ 1 2 3 4 5)
293 | ;;=> 15
294 |
295 | ;;
296 | ;; You can access static fields by
297 | ;; providing the fully qualified class name
298 | ;; followed by a slash (`/`) and the field name,
299 | ;; for example: `java.lang.Long/MAX_VALUE`.
300 | ;;
301 |
302 | java.lang.Long/MAX_VALUE
303 | ;;=> 9223372036854775807
304 |
305 | (- java.lang.Long/MAX_VALUE 1)
306 | ;;=> 9223372036854775806
307 |
308 | (+ 1 java.lang.Long/MAX_VALUE)
309 | ;;=> ArithmeticException integer overflow
310 |
311 |
312 | ;;
313 | ;; Clojure has a number of functions which will
314 | ;; automatically auto-promote the number to be
315 | ;; bigger type in case it doesn't fit in the 64bit
316 | ;; Java Long object. These functions are: `+'`,
317 | ;; `-'` and `*'`
318 | ;;
319 |
320 | (+' 1 java.lang.Long/MAX_VALUE)
321 | ;;=> 9223372036854775808N
322 |
323 | (*' java.lang.Long/MAX_VALUE java.lang.Long/MAX_VALUE)
324 | ;;=> 85070591730234615847396907784232501249N
325 |
326 |
327 | ;;
328 | ;; #### Decimals
329 | ;;
330 | ;; Clojure supports floating point decimals and
331 | ;; exact decimals. Floating point decimals are
332 | ;; mapped to `java.lang.Double` and they evaluate
333 | ;; to themselves. While exact decimals are mapped
334 | ;; to `java.math.BigDecimal` and they also
335 | ;; evaluate to themselves. Use the latter when
336 | ;; you require exact decimals but be careful to
337 | ;; numbers which can't be represented with exact
338 | ;; decimals like: 1 divided by 3 (0.3333333...) as
339 | ;; the the decimal part continue forever.
340 | ;;
341 |
342 | 3.2
343 | ;;=> 3.2
344 |
345 | (type 3.2)
346 | ;;=> java.lang.Double
347 |
348 | 3.2M
349 | ;;=> 3.2M
350 |
351 | (type 3.2M)
352 | ;;=> java.math.BigDecimal
353 |
354 | (+ 0.3 0.3 0.3 0.1) ;; floating point
355 | ;;=> 0.9999999999999999
356 |
357 | (+ 0.3M 0.3M 0.3M 0.1M) ;; big-decimal
358 | ;;=> 1.0M
359 |
360 | (/ 1.0M 3.0M)
361 | ;;=> ArithmeticException Non-terminating decimal expansion; no exact representable decimal result.
362 |
363 | (with-precision 10 (/ 1.0M 3.0M))
364 | ;;=> 0.3333333333M
365 |
366 | ;;
367 | ;; #### Rationals
368 | ;;
369 | ;; Number like 1 divided by 3 are called rational
370 | ;; numbers, and Clojure supports them. You can mix
371 | ;; then in your calculation and as long as you
372 | ;; don't put floating point values it will retain
373 | ;; the precision.
374 | ;;
375 |
376 | (/ 1 3)
377 | ;;=> 1/3
378 |
379 | (type 1/3)
380 | ;;=> clojure.lang.Ratio
381 |
382 | (+ 1/3 1/3 1/3)
383 | ;;=> 1N
384 |
385 | (/ 21 6)
386 | ;;=> 7/2
387 |
388 | (+ 1/3 1/3 1/3 1)
389 | ;;=> 2N
390 |
391 | (+ 1/3 1/3 0.333)
392 | ;;=> 0.9996666666666667
393 |
394 |
395 | ;;
396 | ;;
397 | ;; ### Characters
398 | ;;
399 | ;; So far we have seen the rich support for
400 | ;; numerical values in Clojure. Clojure does
401 | ;; support characters and strings literals as
402 | ;; well. Characters map to `java.lang.Character`,
403 | ;; support Unicode characters and as all
404 | ;; value-types they evaluate to themselves.
405 | ;;
406 |
407 | \a ; this is the character 'a'
408 | \A ; this is the character 'A'
409 | \\ ; this is the character '\'
410 | \u0041 ; this is unicode for 'A'
411 | \tab ; this is the tab character
412 | \newline ; this is the newline character
413 | \space ; this is the space character
414 |
415 | \a ;;=> \a
416 |
417 | (type \a)
418 | ;;=> java.lang.Character
419 |
420 | ;;
421 | ;;
422 | ;; ### Strings
423 | ;;
424 | ;; Strings literals have no surprise. They map to
425 | ;; `java.lang.String`, they are multi-line, like
426 | ;; in Java they are immutable and they evaluate to
427 | ;; themselves.
428 | ;;
429 |
430 | "This is a string"
431 | ;;=> "This is a string"
432 |
433 | (type "This is a string")
434 | ;;=> java.lang.String
435 |
436 | "Strings in Clojure
437 | can be multi lines
438 | as well!!"
439 | ;;=> "Strings in Clojure\n can be multi lines\n as well!!"
440 |
441 | ;;
442 | ;; Via the Java interop. infrastructure you can
443 | ;; call all `java.lang.String` methods directly
444 | ;;
445 |
446 | (.toUpperCase "This is a String")
447 | ;;=> "THIS IS A STRING"
448 |
449 | ;;
450 | ;; You can use the function `str` to concatenate
451 | ;; strings or to convert numbers into strings (via
452 | ;; `Object#toString()` method).
453 | ;;
454 |
455 | (str "This" " is " "a" " concatenation.")
456 | ;;=> "This is a concatenation."
457 |
458 | (str "Number of lines: " 123)
459 | ;;=> "Number of lines: 123"
460 |
461 |
462 | ;;
463 | ;; ### Keywords
464 | ;;
465 | ;; Keywords are labels for things in our programs,
466 | ;; they evaluate to themselves and can be used to
467 | ;; give name to things similarly to Java's
468 | ;; enumerations. They mostly used as key in maps
469 | ;; (we will see this later), and the Clojure
470 | ;; runtime maintains them in a internal pool
471 | ;; (similarly to interned strings in Java.) which
472 | ;; guarantee that only one copy of a particular
473 | ;; keyword will ever exist in a program. For this
474 | ;; reason they provide very fast equality test.
475 | ;; Equality test in Clojure is done via the
476 | ;; function `=` with the same semantic as the
477 | ;; Java's `.equals()` method, while the identity
478 | ;; equality is done via the function `identical?`
479 | ;; which in turn implements the Java's `==`
480 | ;; operator. You can use the function `keyword`
481 | ;; to create a keyword out of a string.
482 | ;;
483 |
484 |
485 | :words
486 | ;;=> :words
487 |
488 | (type :this-is-a-keyword)
489 | ;;=> clojure.lang.Keyword
490 |
491 | (keyword "blue")
492 | ;;=> :blue
493 |
494 | (= :blue :blue)
495 | ;;=> true
496 |
497 | (= (str "bl" "ue") (str "bl" "ue"))
498 | ;;=> true
499 |
500 | (identical? :blue :blue)
501 | ;;=> true
502 |
503 | (identical? (str "bl" "ue") (str "bl" "ue"))
504 | ;;=> false
505 |
506 | (identical? (keyword (str "bl" "ue")) (keyword (str "bl" "ue")))
507 | ;;=> true
508 |
509 | ;;
510 | ;; ### Collections
511 | ;;
512 | ;; In Java the only collection literals available
513 | ;; is the array. Clojure like most modern
514 | ;; languages offers a variety of collection
515 | ;; literals which makes the language more
516 | ;; expressive. Out-of-the-box support is provided for
517 | ;; the following collections literals: single linked
518 | ;; lists, vectors, maps (or dictionaries) and
519 | ;; sets. However Clojure supports a larger number
520 | ;; of data structures which are built with
521 | ;; functions such as: sorted maps, sorted sets,
522 | ;; array maps, hash maps and hash sets. Many more
523 | ;; data structures are available in community maintained
524 | ;; libraries such as graphs, ring buffers and AVL
525 | ;; trees. **All Clojure collections can contain a
526 | ;; mixture of values**.
527 | ;;
528 | ;;
529 | ;; #### Lists
530 | ;;
531 | ;; Clojure has single-linked lists built-in and
532 | ;; like all other Clojure collections are
533 | ;; immutable. Lists guarantee `O(1)` insertion on
534 | ;; the head, `O(n)` traversal and element search.
535 | ;;
536 |
537 | ;; to create a list you can use the function `list`
538 |
539 | (list 1 2 3 4 5)
540 | ;;=> (1 2 3 4 5)
541 |
542 | ;; to "add" an element on the front of the list you can
543 | ;; use the `cons` function.
544 |
545 | (cons 0 (list 1 2 3 4 5))
546 | ;;=> (0 1 2 3 4 5)
547 |
548 | ;; As the output suggest the lists literals in
549 | ;; Clojure are expressed with a sequence of values
550 | ;; surrounded by brackets, which is the same of
551 | ;; the function call. That is the reason why the
552 | ;; following line throws an error.
553 |
554 | (1 2 3 4 5)
555 | ;;=> ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn
556 |
557 | ;; To be able to express a list of values as a
558 | ;; literal we have to used the `quote` form which
559 | ;; it will preserve the list without initiate the
560 | ;; function call.
561 |
562 | (quote (1 2 3 4 5))
563 | ;;=> (1 2 3 4 5)
564 |
565 | ;;
566 | ;; As syntax sugar we can use the single quote
567 | ;; sign `'` instead of the longer `(quote ,,,)`
568 | ;; form.
569 | ;;
570 |
571 | '(1 2 3 4 5)
572 | ;;=> (1 2 3 4 5)
573 |
574 | '(1 "hi" :test 4/5 \c)
575 | ;;=> (1 "hi" :test 4/5 \c)
576 |
577 | ;;
578 | ;; you can get the head of the list with the
579 | ;; function `first` and use `rest` or `next` to
580 | ;; get the tail. `count` returns the number of
581 | ;; elements in it. `nth` returns the nth element
582 | ;; of the list, while `last` returns last item in
583 | ;; the list.
584 | ;;
585 |
586 | (first '(1 2 3 4 5))
587 | ;;=> 1
588 |
589 | (rest '(1 2 3 4 5))
590 | ;;=> (2 3 4 5)
591 |
592 | (next '(1 2 3 4 5))
593 | ;;=> (2 3 4 5)
594 |
595 | (rest '(1))
596 | ;;=> ()
597 |
598 | (next '(1))
599 | ;;=> nil
600 |
601 | (count '(5))
602 | ;;=> 1
603 |
604 | (count '(1 2 3 4 5))
605 | ;;=> 5
606 |
607 | (nth '(1 2 3 4 5) 0)
608 | ;;=> 1
609 |
610 | (nth '(1 2 3 4 5) 1)
611 | ;;=> 2
612 |
613 | (nth '(1 2 3 4 5) 10)
614 | ;;=> IndexOutOfBoundsException
615 |
616 | (nth '(1 2 3 4 5) 10 :not-found)
617 | ;;=> :not-found
618 |
619 | (last '(1 2 3 4 5))
620 | ;;=> 5
621 |
622 | (last '(1))
623 | ;;=> 1
624 |
625 | (last '())
626 | ;;=> nil
627 |
628 | ;;
629 | ;; #### Vectors
630 | ;;
631 | ;; Vectors are collections of values which are
632 | ;; indexed by their position in the vector
633 | ;; (starting from 0) called **index**. Insertion
634 | ;; at the end of the vector is `near O(1)` as well
635 | ;; as retrieval of an element by it's index. The
636 | ;; literals is expressed with a sequence of values
637 | ;; surrounded by square brackets or you can use
638 | ;; the `vector` function to construct one. You
639 | ;; can append an element at the end of the vector
640 | ;; with `conj` and use `get` to retrieve an
641 | ;; element in a specific index. Function such as
642 | ;; `first`, `next` `rest`, `last` and `count` will
643 | ;; work just as fine with Vectors.
644 |
645 | [1 2 3 4 5]
646 | ;;=> [1 2 3 4 5]
647 |
648 | [1 "hi" :test 4/5 \c]
649 | ;;=> [1 "hi" :test 4/5 \c]
650 |
651 | (vector 1 2 3 4 5)
652 | ;;=> [1 2 3 4 5]
653 |
654 | (conj [1 2 3 4 5] 6)
655 | ;;=> [1 2 3 4 5 6]
656 |
657 | (count [1 2])
658 | ;;=> 2
659 |
660 | (first [:a :b :c])
661 | ;;=> :a
662 |
663 | (get [:a :b :c] 1)
664 | ;;=> :b
665 |
666 | ([:a :b :c] 1)
667 | ;;=> :b
668 |
669 | (get [:a :b :c] 10)
670 | ;;=> nil
671 |
672 | (get [:a :b :c] 10 :z)
673 | ;;=> :z
674 |
675 | ;;
676 | ;; One important thing to note is that Clojure's
677 | ;; data-structures are persistent which has
678 | ;; anything to do with the durability (like: disk
679 | ;; persistence). Persistent data structure do have
680 | ;; structural sharing. To understand more about
681 | ;; this you can read the following blog post:
682 | ;; [Understanding Clojure's Persistent](http://hypirion.com/musings/understanding-persistent-vector-pt-1)
683 | ;;
684 | ;;
685 | ;; #### Maps
686 | ;;
687 | ;; Maps are associative data structures (often
688 | ;; called dictionaries) which maps keys to their
689 | ;; corresponding value. Maps have a literal form
690 | ;; which can be expressed by any number of
691 | ;; key/value pairs surrounded by curly brackets,
692 | ;; or by using `hash-map` or `array-map`
693 | ;; functions. Hash-maps provides a `near O(1)`
694 | ;; insertion time and `near O(1)` seek time. You
695 | ;; can use `assoc` to "add or overwrite" an new
696 | ;; pair, `dissoc` to "remove" a key and its value,
697 | ;; and use `get` to retrieve the value of a given
698 | ;; key.
699 |
700 | {"jane" "jane@acme.com"
701 | "fred" "fred@acme.com"
702 | "rob" "rob@acme.com"}
703 | ;;=> {"jane" "jane@acme.com", "fred" "fred@acme.com", "rob" "rob@acme.com"}
704 |
705 | {:a 1, :b 2, :c 3}
706 | ;;=> {:a 1, :b 2, :c 3}
707 |
708 | (hash-map :a 1, :b 2, :c 3)
709 | ;;=> {:c 3, :b 2, :a 1}
710 |
711 | (array-map :a 1, :b 2, :c 3)
712 | ;;=> {:a 1, :b 2, :c 3}
713 |
714 | (assoc {:a 1, :b 2, :c 3} :d 4)
715 | ;;=> {:a 1, :b 2, :c 3, :d 4}
716 |
717 | (assoc {:a 1, :b 2, :c 3} :b 10)
718 | ;;=> {:a 1, :b 10, :c 3}
719 |
720 | (dissoc {:a 1, :b 2, :c 3} :b)
721 | ;;=> {:a 1, :c 3}
722 |
723 | (count {:a 1, :b 2, :c 3})
724 | ;;=> 3
725 |
726 | (get {:a 1, :b 2, :c 3} :a)
727 | ;;=> 1
728 |
729 | (get {:a 1, :b 2, :c 3} :a :not-found)
730 | ;;=> 1
731 |
732 | (get {:a 1, :b 2, :c 3} :ZULU :not-found)
733 | ;;=> :not-found
734 |
735 | (:a {:a 1, :b 2, :c 3})
736 | ;;=> 1
737 |
738 | ({:a 1, :b 2, :c 3} :a)
739 | ;;=> 1
740 |
741 | ;;
742 | ;; #### Sets
743 | ;;
744 | ;; Sets are a type of collection which doesn't
745 | ;; allow for duplicate values. While lists and
746 | ;; vector can have duplicate elements, set
747 | ;; eliminates all duplicates. Clojure has a
748 | ;; literal form for sets which is expressed by a
749 | ;; sequence of values surrounded by `#{
750 | ;; }`. Otherwise you construct a set using the
751 | ;; `set` function. With `conj` you can "add" a
752 | ;; new element to an existing set, and `disj` to
753 | ;; "remove" an element from the set. With
754 | ;; `clojure.set/union`, `clojure.set/difference`
755 | ;; and `clojure.set/intersection` you have typical
756 | ;; sets operations. `count` returns the number of
757 | ;; elements in the set in `O(1)` time.
758 |
759 | #{1 2 4}
760 | ;;=> #{1 4 2}
761 |
762 | ;;
763 | ;; If you put twice the same element
764 | ;; your Clojure code will be syntactically
765 | ;; incorrect. At the REPL you will get
766 | ;; an error.
767 | ;;
768 | ;; #{ 1 1 3 5}
769 | ;; ;;=> IllegalArgumentException Duplicate key: 1
770 |
771 | #{:a 4 5 :d "hello"}
772 | ;;=> #{"hello" 4 5 :d :a}
773 |
774 | (type #{:a :z})
775 | ;;=> clojure.lang.PersistentHashSet
776 |
777 | (set [:a :b :c])
778 | ;;=> #{:c :b :a}
779 |
780 | (conj #{:a :c} :b)
781 | ;;=> #{:c :b :a}
782 |
783 | (conj #{:a :c} :c)
784 | ;;=> #{:c :a}
785 |
786 | (disj #{:a :b :c} :b)
787 | ;;=> #{:c :a}
788 |
789 | (clojure.set/union #{:a} #{:a :b} #{:c :a})
790 | ;;=> #{:c :b :a}
791 |
792 | (clojure.set/difference #{:a :b} #{:c :a})
793 | ;;=> #{:b}
794 |
795 | (clojure.set/intersection #{:a :b} #{:c :a})
796 | ;;=> #{:a}
797 |
798 |
799 | ;;
800 | ;; ### The sequence abstraction
801 | ;;
802 | ;; One of the most powerful abstraction of
803 | ;; Clojure's data structures is the `sequence`
804 | ;; (`clojure.lang.ISeq`) which all data structure
805 | ;; implements. This interface resembles to a Java
806 | ;; iterator, and it implements methods like
807 | ;; `first()`, `rest()`, `more()` and `cons()`. The
808 | ;; power of this abstraction is that it is general
809 | ;; enough to be used in all data structures
810 | ;; (lists, vectors, maps, sets and even strings
811 | ;; can all produce sequences) and you have loads
812 | ;; of functions which manipulates it. Functions
813 | ;; such as `first`, `rest`, `next` and `last` and
814 | ;; many others such as `reverse`, `shuffle`,
815 | ;; `drop`, `take`, `partition`, `filter` etc are
816 | ;; all built on top of the sequence abstraction.
817 | ;; So if you create your own data-structure and
818 | ;; you implement the four methods of the
819 | ;; `clojure.lang.ISeq` interface you can benefit
820 | ;; from all these function without having to
821 | ;; re-implement them for your specific
822 | ;; data-structure.
823 | ;;
824 | ;; You can create a sequence explicitly with the
825 | ;; `seq` function but there are loads of functions
826 | ;; which already return a sequence. The sequence
827 | ;; of a list is the list itself, other
828 | ;; data-structures will produce one. Maps will
829 | ;; produce a sequence of map entries, where each
830 | ;; entry can be represented like a vector of two
831 | ;; values (the key and it's value.)
832 | ;;
833 |
834 | (seq '(1 2 3 4))
835 | ;;=> (1 2 3 4)
836 |
837 | (seq [1 2 3 4])
838 | ;;=> (1 2 3 4)
839 |
840 | (seq #{1 2 3 4})
841 | ;;=> (1 4 3 2)
842 |
843 | (seq {:a 1, :b 2, :c 3})
844 | ;;=> ([:a 1] [:b 2] [:c 3])
845 |
846 | ;;
847 | ;; There is no need to call `seq` explicitly, in
848 | ;; most of the cases, functions which take a
849 | ;; sequence can work with all data structures
850 | ;; directly.
851 | ;;
852 |
853 | (first [1 2 3 4])
854 | ;;=> 1
855 |
856 | (take 3 [:a :b :c :d])
857 | ;;=> (:a :b :c)
858 |
859 | (shuffle [1 2 3 4])
860 | ;;=> [1 3 2 4]
861 |
862 | (shuffle #{1 2 3 4})
863 | ;;=> [2 4 1 3]
864 |
865 | (reverse [1 2 3 4])
866 | ;;=> (4 3 2 1)
867 |
868 | (last (reverse {:a 1 :b 2 :c 3}))
869 | ;;=> [:a 1]
870 |
871 | ;;
872 | ;; Because the Clojure String implements the sequence
873 | ;; abstraction, you can treat the String as a sequence
874 | ;; of characters.
875 | ;;
876 |
877 | (seq "Hello World!")
878 | ;;=> (\H \e \l \l \o \space \W \o \r \l \d \!)
879 |
880 | (first "Hello")
881 | ;;=> \H
882 |
883 | (rest "Hello")
884 | ;;=> (\e \l \l \o)
885 |
886 | (count "Hello World!")
887 | ;;=> 12
888 |
889 | ;;
890 | ;; #### Lazy Sequences
891 | ;;
892 | ;; Some of the sequences produced by the core
893 | ;; library are lazy which means that the entire
894 | ;; collection won't be created (*realised*) all at
895 | ;; once. At first, an iterator like structure is
896 | ;; created, with subsequent calls to `next()`
897 | ;; causing chunks of items to be
898 | ;; fetched/computed. This is a very important
899 | ;; element of the language which allows the easy
900 | ;; expression of infinite sequences without
901 | ;; running out of memory. For example the function
902 | ;; `range` returns a lazy sequence of natural
903 | ;; numbers between two given numbers. But when it
904 | ;; is called without arguments it returns a lazy
905 | ;; sequence of all natural numbers. Yet it
906 | ;; doesn't run out of memory. What it really
907 | ;; produces is just an iterator that computes the
908 | ;; next chunk of numbers when `next()` is called.
909 | ;;
910 | ;; _NOTE: As subsequent calls are made to
911 | ;; `next()`, it is advisable not to reference/hold
912 | ;; earlier lazy sequence items for too long. This
913 | ;; allows earlier items to be cleared from memory
914 | ;; and prevents OOM (OutOfMemoryError)._
915 |
916 | (range 5 10)
917 | ;;=> (5 6 7 8 9)
918 |
919 | ;; _**WARNING!!!** Evaluating this from your REPL
920 | ;; might hang/crash your process_, as it will try
921 | ;; evaluate an infinite lazy sequence all at once.
922 |
923 | (range)
924 | ;;=> (0 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 ...)
925 |
926 | (take 10 (range))
927 | ;;=> (0 1 2 3 4 5 6 7 8 9)
928 |
929 | ;;
930 | ;; ### Regular expression patterns
931 | ;;
932 | ;; Clojure also supports regular expression
933 | ;; patterns as literals which directly map to the
934 | ;; `java.util.Pattern` and offers a number of
935 | ;; functions to match, find and extract patterns.
936 | ;; For example: `re-find` and `re-seq` to find
937 | ;; respectively the first or all occurrences of a
938 | ;; matching pattern. With `re-pattern` you can
939 | ;; programmatically create a function out of a
940 | ;; string.
941 | ;;
942 |
943 | #"[\w\d.-]+@[\w\d-.]+\.[\w]+"
944 | ;;=> #"[\w\d.-]+@[\w\d-.]+\.[\w]+"
945 |
946 | (type #"[\w\d.-]+@[\w\d-.]+\.[\w]+")
947 | ;;=> java.util.regex.Pattern
948 |
949 | (re-find #"[0-9]+" "only 123 numbers")
950 | ;;=> "123"
951 |
952 | (re-find #"[0-9]+" "no numbers")
953 | ;;=> nil
954 |
955 | (re-find #"[\w\d.-]+@[\w\d-.]+\.[\w]+"
956 | "bob.smith@acme.org")
957 | ;;=> "bob.smith@acme.org"
958 |
959 | (if (re-find #"^[\w\d.-]+@[\w\d-.]+\.[\w]+$"
960 | "bob.smith@acme.org")
961 | "it's an email"
962 | "it's not an email")
963 | ;;=> "it's an email"
964 |
965 | (re-seq #"[0-9]+" "25, 43, 54, 12, 15, 65")
966 | ;;=> ("25" "43" "54" "12" "15" "65")
967 |
968 | (re-pattern "[0-9]{1,3}(\\.[0-9]{1,3}){3}")
969 | ;;=> #"[0-9]{1,3}(\.[0-9]{1,3}){3}"
970 |
971 | (re-find
972 | (re-pattern "[0-9]{1,3}(\\.[0-9]{1,3}){3}")
973 | "my IP is: 192.168.0.12")
974 | ;;=> ["192.168.0.12" ".12"]
975 |
976 | ;;
977 | ;; Using `re-matcher`, `re-matches`, `re-groups`
978 | ;; allows you to have fine control over the capturing
979 | ;; groups.
980 |
981 |
982 | ;;
983 | ;; ### Symbols and Vars
984 | ;;
985 | ;; Symbols in Clojure are a way to identify things
986 | ;; in your programs which may have various values
987 | ;; at runtime. Like in a mathematical notation, `x`
988 | ;; is something not known which could assume
989 | ;; several different values. In a programming
990 | ;; context, Clojure symbols are similar to
991 | ;; variables in other languages but not exactly.
992 | ;; In other languages variables are places where
993 | ;; you store information, symbols in Clojure
994 | ;; cannot contain data themselves. Vars in
995 | ;; Clojure are the containers of data (one type
996 | ;; of), and symbols are a way to identify them and
997 | ;; give vars meaningful names for your program.
998 | ;;
999 | ;; Everything we have seen so far were pure
1000 | ;; values, as such they were all evaluating to
1001 | ;; themselves. Like `42` is just `42`, the
1002 | ;; following vector `[:a "hello" 9]` just
1003 | ;; evaluates to itself, it is just a value.
1004 | ;; Symbols, however, during the evaluation
1005 | ;; are replaced with the current value of var
1006 | ;; they are pointing to. If you try to evaluate
1007 | ;; a var which is undefined you will get an error.
1008 | ;;
1009 | ;; Symbols are organised into namespaces. We will
1010 | ;; not explore much about namespaces here, but it
1011 | ;; will suffice to know that symbols belong to a
1012 | ;; namespace in which they assume a particular
1013 | ;; value, and you can have the same symbol name in
1014 | ;; different namesapce pointing to different
1015 | ;; values.
1016 | ;;
1017 | ;; In Clojure symbols start with a letter, and can
1018 | ;; contain letters, numbers, dashes, some
1019 | ;; punctuation marks and other
1020 | ;; characters. Basically anything which doesn't
1021 | ;; belong in the Clojure syntax (following
1022 | ;; characters aren't accepted in symbols name
1023 | ;; `@#,/.[]{}()`) anything else is a valid symbol.
1024 | ;;
1025 | ;; You can create symbols by quoting a word with
1026 | ;; the `quote` function or the single quote
1027 | ;; character, you can use the function `symbol`,
1028 | ;; but most commonly you will use symbols in place
1029 | ;; of vars and locals which are define with the
1030 | ;; special forms `def` and `let` respectively. A
1031 | ;; symbol name which is NOT quoted will be
1032 | ;; resolved to the current value of the associated
1033 | ;; var.
1034 | ;;
1035 | ;; As we will see in the following examples symbols
1036 | ;; are un-typed and can refer to any Clojure value,
1037 | ;; including `nil`
1038 | ;;
1039 |
1040 | (symbol "username")
1041 | ;;=> username
1042 |
1043 | (type (symbol "username"))
1044 | ;;=> clojure.lang.Symbol
1045 |
1046 | (type 'username)
1047 | ;;=> clojure.lang.Symbol
1048 |
1049 | (def username "bruno1")
1050 | ;;=> #'learn-clojure.basics/username
1051 |
1052 | username
1053 | ;;=> "bruno1"
1054 |
1055 | age ;; undefined var produces error
1056 | ;;=> Unable to resolve symbol: age in this context
1057 |
1058 | (def age 21)
1059 | ;;=> #'learn-clojure.basics/age
1060 |
1061 | age
1062 | ;;=> 21
1063 |
1064 | (type 'age)
1065 | ;;=> clojure.lang.Symbol
1066 |
1067 | (type age)
1068 | ;;=> java.lang.Long
1069 |
1070 | (def user {:username "bruno1"
1071 | :score 12345
1072 | :level 32
1073 | :achievements #{:fast-run :precision10
1074 | :strategy}})
1075 | ;;=> #'learn-clojure.basics/user
1076 |
1077 | user
1078 | ;;=> {:username "bruno1", :score 12345, :level 32, :achievements #{:precision10 :strategy :fast-run}}
1079 |
1080 | (def user nil)
1081 | ;;=> #'learn-clojure.basics/user
1082 |
1083 | user
1084 | ;;=> nil
1085 |
1086 |
1087 | ;;
1088 | ;; ### Immutability
1089 | ;;
1090 | ;; All basics data-types in Clojure are immutable,
1091 | ;; including the collections. This is a very
1092 | ;; important aspect of Clojure approach to
1093 | ;; functional programming. In Clojure functions
1094 | ;; transform values into new values and values are
1095 | ;; just values. Since it is absurd to think of
1096 | ;; changing a number (1 is always 1),
1097 | ;; composite data structures are treated in the same way.
1098 | ;; So functions do not mutate values they just produce new ones.
1099 | ;; Like adding `1` to `42` produces `43` but
1100 | ;; doesn't really change the number `42` as it keeps on
1101 | ;; existing on its own, adding an element to a list will
1102 | ;; produce a new list but the old one will still be same
1103 | ;; and unmodified.
1104 | ;;
1105 | ;; The advantage of the immutability is that
1106 | ;; values (even deeply nested and complex
1107 | ;; structures) can be safely shared across threads
1108 | ;; and with function callers without worrying
1109 | ;; about unsafe or uncoordinated changes. This
1110 | ;; simple constraint makes Clojure programs so
1111 | ;; much easier to reason about, as the only way to
1112 | ;; produce a new value is via a functional
1113 | ;; transformation.
1114 | ;;
1115 |
1116 | (def colours '(:red :green :blue))
1117 | ;;=> #'learn-clojure.basics/colours
1118 |
1119 | (def new-colours (cons :black colours))
1120 | ;;=> #'learn-clojure.basics/new-colours
1121 |
1122 | new-colours
1123 | ;;=> (:black :red :green :blue)
1124 |
1125 | colours
1126 | ;;=> (:red :green :blue)
1127 |
1128 | (def user {:username "bruno1"
1129 | :score 12345
1130 | :level 32})
1131 | ;;=> #'learn-clojure.basics/user
1132 |
1133 | (def user' (assoc user :level 33))
1134 | ;;=> #'learn-clojure.basics/user'
1135 |
1136 | user'
1137 | ;;=> {:username "bruno1", :score 12345, :level 33}
1138 |
1139 | user
1140 | ;;=> {:username "bruno1", :score 12345, :level 32}
1141 |
1142 | ;;
1143 | ;; ### Functions
1144 | ;;
1145 | ;; So far we have seen how to represent data in
1146 | ;; our system, now we will see how to make sense
1147 | ;; of this data and how to
1148 | ;; extract/process/transform it. The way we
1149 | ;; express this in Clojure is via functions.
1150 | ;;
1151 | ;;
1152 | ;; #### Purity
1153 | ;;
1154 | ;; While Clojure doesn't enforce purity at
1155 | ;; compiler level, it certainly promotes
1156 | ;; pure-functions. Pure functions are those
1157 | ;; functions in which the processing doesn't use
1158 | ;; or produce any side effect, which means it will
1159 | ;; use only the input parameters to compute the
1160 | ;; resulting value, and given the same parameters
1161 | ;; it will always produce the same result.
1162 | ;;
1163 | ;; When a function given a certain input, always
1164 | ;; produces the same output it is said to be
1165 | ;; __referentially transparent__, because the
1166 | ;; function call itself can be replaced with
1167 | ;; its value without altering the rest of the
1168 | ;; expression.
1169 | ;;
1170 | ;; Pure functions are important because
1171 | ;; they are incredibly easy to test as
1172 | ;; they don't depend on external state.
1173 | ;;
1174 | ;; Here are two examples: the first is the function `+`
1175 | ;; which we have already seen, and the second is the
1176 | ;; function `rand-int` which produce a random
1177 | ;; integer number between `0` and the given
1178 | ;; integer. While the first is pure because given
1179 | ;; the same input parameters it will always produce the
1180 | ;; same output, the second one given the same
1181 | ;; input returns a different value every time.
1182 | ;;
1183 |
1184 | (+ 1 2 3)
1185 | ;;=> 6
1186 |
1187 | (rand-int 100)
1188 | ;;=> 18
1189 |
1190 | (rand-int 100)
1191 | ;;=> 85
1192 |
1193 | (+ 1 2 (+ 1 1 1)) ;; (+ 1 1 1) is referentially transparent
1194 | ;;=> 6
1195 |
1196 | ;;
1197 | ;; #### Function definition
1198 | ;;
1199 | ;; To define a function you have to use the
1200 | ;; special form `fn` or `defn` with the following
1201 | ;; syntax.
1202 | ;;
1203 | ;; for example if we want to define a function
1204 | ;; which increments the input parameters by 1 you
1205 | ;; will write something as follow:
1206 | ;;
1207 | ;; ```
1208 | ;; /- fn, special form
1209 | ;; / parameter vector, 1 param called `n`
1210 | ;; | | body -> expression to evaluate when
1211 | ;; | | | this function is called
1212 | ;; (fn [n] (+ n 1))
1213 | ;; ```
1214 | ;;
1215 | ;; This is the simplest way to define a function.
1216 | ;;
1217 | ;; Now to refer to this function in our code we
1218 | ;; need to give it a name. We can do so with `def`
1219 | ;; as we done earlier.
1220 | ;;
1221 |
1222 | (def plus-one (fn [n] (+ n 1)))
1223 | ;;=> #'learn-clojure.basics/plus-one
1224 |
1225 | (plus-one 10)
1226 | ;;=> 11
1227 |
1228 | (plus-one -42)
1229 | ;;=> -41
1230 |
1231 | ;;
1232 | ;; As mentioned earlier, during the evaluation process
1233 | ;; the symbol `plus-one` is simply replaced with
1234 | ;; its value, in the same way we can replace the
1235 | ;; symbol with the function definition and obtain
1236 | ;; the same result. So symbols can also refer to
1237 | ;; functions.
1238 | ;;
1239 |
1240 | ((fn [n] (+ n 1)) 10)
1241 | ;;=> 11
1242 |
1243 | ((fn [n] (+ n 1)) -42)
1244 | ;;=> -41
1245 |
1246 | ;;
1247 | ;; Since defining functions is very common, there
1248 | ;; is a shorthand to the idiom `(def funciton-name
1249 | ;; (fn [parameter list] (expression)))` via the
1250 | ;; `defn` form which just combines the `def` and
1251 | ;; `fn` forms. So we can redefine the previous
1252 | ;; function in the following way:
1253 | ;;
1254 |
1255 | (defn plus-one [n]
1256 | (+ n 1))
1257 | ;;=> #'learn-clojure.basics/plus-one
1258 |
1259 | (plus-one 1)
1260 | ;;=> 2
1261 |
1262 | ;;
1263 | ;; It is good practice to include a short description (called `docstring`)
1264 | ;; in the function.
1265 | ;;
1266 |
1267 | (defn plus-one
1268 | "Returns a number which is one greater than the given `n`."
1269 | [n]
1270 | (+ n 1))
1271 | ;;=> #'learn-clojure.basics/plus-one
1272 |
1273 | ;;
1274 | ;; **NOTE:** that Clojure core already contains
1275 | ;; such a function and it is called `inc`, while the
1276 | ;; function `dec` decrements by 1 the given value.
1277 | ;;
1278 |
1279 | (inc 10)
1280 | ;;=> 11
1281 |
1282 |
1283 | ;;
1284 | ;; In the following example we see how to create
1285 | ;; functions with multiple parameters. Let's
1286 | ;; assume we have to create a function which
1287 | ;; create a corporate email address for its
1288 | ;; employee. Oftentimes this type of email follows
1289 | ;; a very specific pattern In this case we will
1290 | ;; take the first letter of the name followed by
1291 | ;; the lastname then `@` the company domain.
1292 | ;;
1293 |
1294 | (defn email-address [firstname lastname domain]
1295 | (clojure.string/lower-case (str (first firstname) lastname "@" domain)))
1296 | ;;=> #'learn-clojure.basics/email-address
1297 |
1298 | (email-address "John" "Smith" "acme.org")
1299 | ;;=> "jsmith@acme.org"
1300 |
1301 | (email-address "Walter" "White" "breakingbad.org")
1302 | ;;=> "wwhite@breakingbad.org"
1303 |
1304 | ;;
1305 | ;; #### Function with multi-arities
1306 | ;;
1307 | ;; So far we've seen how to create functions
1308 | ;; which accept a fix number of parameters.
1309 | ;; In Clojure is possible to create functions
1310 | ;; which accept different set of 'arities'.
1311 | ;;
1312 |
1313 | (defn simple-greet
1314 | ([]
1315 | (simple-greet "World"))
1316 | ([name]
1317 | (str "Hello " name "!")))
1318 | ;;=> #'learn-clojure.basics/simple-greet
1319 |
1320 | (simple-greet)
1321 | ;;=> "Hello World!"
1322 |
1323 | (simple-greet "Fred")
1324 | ;;=> "Hello Fred!"
1325 |
1326 |
1327 | (defn greet
1328 | ([]
1329 | "Hey, Stranger!")
1330 | ([name]
1331 | (str "Hello " name))
1332 | ([firstname lastname]
1333 | (str "Hi, you must be: " lastname ", " firstname " " lastname))
1334 | ([title firstname lastname]
1335 | (str "Hello " title " " firstname " " lastname)))
1336 | ;;=> #'learn-clojure.basics/greet
1337 |
1338 | (greet)
1339 | ;;=> "Hey, Stranger!"
1340 |
1341 | (greet "James")
1342 | ;;=> "Hello James"
1343 |
1344 | (greet "James" "Bond")
1345 | ;;=> "Hi, you must be: Bond, James Bond"
1346 |
1347 | (greet "Dr" "John H." "Watson")
1348 | ;;=> "Hello Dr John H. Watson"
1349 |
1350 |
1351 | ;;
1352 | ;; It is also possible to create functions
1353 | ;; which have any number of parameters.
1354 | ;; these are called `variadic functions`.
1355 | ;;
1356 |
1357 | (defn de-dup [& names]
1358 | (seq (set names)))
1359 | ;;=> #'learn-clojure.basics/de-dup
1360 |
1361 | (de-dup "John" "Fred" "Lara" "John" "John" "Susan")
1362 | ;;=> ("Susan" "Fred" "John" "Lara")
1363 |
1364 | (defn short-name [firstname & names]
1365 | (str firstname " " (last names)))
1366 | ;;=> #'learn-clojure.basics/short-name
1367 |
1368 | (short-name "Maria" "Teresa" "Jiulia" "Ramírez de Arroyo" "García")
1369 | ;;=> "Maria García"
1370 |
1371 | ;;
1372 | ;; #### High-order functions
1373 | ;;
1374 | ;; In Clojure functions are reified contructs,
1375 | ;; therefore we can threat them as normal
1376 | ;; values. As such functions can be passed as
1377 | ;; parameters of function or returned as result of
1378 | ;; function call.
1379 | ;;
1380 |
1381 | (defn is-commutative? [op a b]
1382 | (= (op a b) (op b a)))
1383 | ;;=> #'learn-clojure.basics/is-commutative?
1384 |
1385 | (is-commutative? + 3 7)
1386 | ;;=> true
1387 |
1388 | (is-commutative? / 3 7)
1389 | ;;=> false
1390 |
1391 |
1392 | (defn multiplier [m]
1393 | (fn [n]
1394 | (* n m)))
1395 | ;;=> #'learn-clojure.basics/multiplier
1396 |
1397 | (def doubler (multiplier 2))
1398 | ;;=> #'learn-clojure.basics/doubler
1399 |
1400 | (doubler 5)
1401 | ;;=> 10
1402 |
1403 | (doubler 10)
1404 | ;;=> 20
1405 |
1406 | (def mult-10x (multiplier 10))
1407 | ;;=> #'learn-clojure.basics/mult-10x
1408 |
1409 | (mult-10x 35)
1410 | ;;=> 350
1411 |
1412 | ;;
1413 | ;; #### Anonymous functions or lambda functions
1414 | ;;
1415 | ;; Oftentimes you want to create a function for a
1416 | ;; specific task in a local context. Such
1417 | ;; functions don't have any reason to have a
1418 | ;; global name as they are meaningful only in that
1419 | ;; specific context, in this case you can create
1420 | ;; anonymous functions (also called lambda
1421 | ;; function) and Clojure has some support to make
1422 | ;; this easier. We already seen an example of an
1423 | ;; anonymous function with our very first function
1424 | ;; example.
1425 | ;;
1426 |
1427 | (fn [n] (+ n 1)) ;;Evaluates to an object/value. In Clojure, functions are values
1428 | ;;=> #function[learn-clojure.basics/eval20002/fn--20003]
1429 |
1430 | ((fn [n] (+ n 1)) 10)
1431 | ;;=> 11
1432 |
1433 | ;;
1434 | ;; here the function we built hasn't got a name.
1435 | ;; We then used a `def` form to give it the
1436 | ;; `plus-one` name.
1437 | ;; This anonymous function could also be written
1438 | ;; in the following way.
1439 |
1440 | #(+ % 1)
1441 | ;;=> #function[learn-clojure.basics/eval20028/fn--20029]
1442 |
1443 | (#(+ % 1) 10)
1444 | ;;=> 11
1445 |
1446 | ;;
1447 | ;; In this function the symbol `%` replace the argument
1448 | ;; If you have more than one parameter you can denote them as
1449 | ;; `%1` (or `%`), `%2`, `%3`, `%4` ...
1450 | ;;
1451 | ;; for example in our `is-commutative?` function we expect
1452 | ;; and operation which accept two arguments:
1453 |
1454 | (is-commutative? #(+ %1 %2) 9 8)
1455 | ;;=> true
1456 |
1457 | ;;
1458 | ;; #### Closures
1459 | ;;
1460 | ;; Closures (with the `s`) are lambdas which refer
1461 | ;; to a context (or values from another context).
1462 | ;; These functions are said to be "closing over"
1463 | ;; the environment. This means that it can access
1464 | ;; parameters and values which are NOT in the
1465 | ;; parameters list.
1466 | ;;
1467 | ;; Like in our `multiplier` function example, the
1468 | ;; returned function is closing over the value `m`
1469 | ;; which is not in its parameter list but it is a
1470 | ;; parameter of the parent context the
1471 | ;; `multiplier` fn. While `n` is a normal
1472 | ;; parameter `m` is the value we are "closing
1473 | ;; over" providing a context for that function.
1474 |
1475 | (defn multiplier [m]
1476 | (fn [n]
1477 | (* n m)))
1478 | ;;=> #'learn-clojure.basics/multiplier
1479 |
1480 | ;;
1481 | ;; Let's see another example. Here we want to
1482 | ;; create a function which takes a number and
1483 | ;; return a logical value representing whether the
1484 | ;; number is between two limits (limits included).
1485 | ;; For this purpose we can use the function `>=`
1486 | ;; which returns whether a number is greater or
1487 | ;; equal then the other one.
1488 | ;;
1489 | ;; Other similar functions are `>`, `<`, `<=`, `=` and `not=`.
1490 | ;;
1491 |
1492 | (>= 10 3) ;; like 10 >= 3
1493 | ;;=> true
1494 |
1495 | (>= 3 10)
1496 | ;;=> false
1497 |
1498 | (>= 6 6)
1499 | ;;=> true
1500 |
1501 | (>= 6 5 2)
1502 | ;;=> true
1503 |
1504 |
1505 | (defn limit-checker [min max]
1506 | (fn [n]
1507 | (>= max n min)))
1508 | ;;=> #'learn-clojure.basics/limit-checker
1509 |
1510 | (def legal-value (limit-checker 5 10))
1511 | ;;=> #'learn-clojure.basics/legal-value
1512 |
1513 | (legal-value 1)
1514 | ;;=> false
1515 |
1516 | (legal-value 7)
1517 | ;;=> true
1518 |
1519 | (legal-value 10)
1520 | ;;=> true
1521 |
1522 | (legal-value 11)
1523 | ;;=> false
1524 |
1525 | ;;
1526 | ;; #### Recursion
1527 | ;;
1528 | ;; A recursive function is a function which
1529 | ;; calls itself. There are two types of recursion
1530 | ;; the mundane recursion and the tail recursion.
1531 | ;;
1532 | ;; Let's see an example of both with this function
1533 | ;; which given a number it calculates the sum of
1534 | ;; all natural numbers from 1 to the given
1535 | ;; number.
1536 |
1537 | (defn sum1
1538 | ([n]
1539 | (sum1 n 0))
1540 | ([n accumulator]
1541 | (if (< n 1)
1542 | accumulator
1543 | ;; else
1544 | (sum1 (dec n) (+ n accumulator)))))
1545 | ;;=> #'learn-clojure.basics/sum1
1546 |
1547 | (sum1 1)
1548 | ;;=> 1
1549 |
1550 | (sum1 3)
1551 | ;;=> 6
1552 |
1553 | (sum1 10)
1554 | ;;=> 55
1555 |
1556 | ;;
1557 | ;; This type of recursion is called mundane
1558 | ;; recursion and every new call it allocates one
1559 | ;; new frame on the stack so if you run this with
1560 | ;; high enough numbers it will blow your stack.
1561 | ;;
1562 |
1563 | (sum1 10000)
1564 | ;;=> StackOverflowError
1565 |
1566 | ;;
1567 | ;; Let's see how we can write this
1568 | ;; function with a tail recursion using
1569 | ;; `recur`.
1570 | ;;
1571 |
1572 | (defn sum2
1573 | ([n]
1574 | (sum2 n 0))
1575 | ([n accumulator]
1576 | (if (< n 1)
1577 | accumulator
1578 | ;; else
1579 | (recur (dec n) (+ n accumulator)))))
1580 | ;;=> #'learn-clojure.basics/sum2
1581 |
1582 | (sum2 10)
1583 | ;;=> 55
1584 |
1585 | (sum2 10000)
1586 | ;;=> 50005000
1587 |
1588 | (sum2 1000000)
1589 | ;;=> 500000500000
1590 |
1591 | (sum2 100000000)
1592 | ;;=> 5000000050000000
1593 |
1594 | ;;
1595 | ;; As you can see the function can recur much
1596 | ;; more without exploding this is because
1597 | ;; it doesn't consume stack.
1598 | ;; The tail recursion can be used only when
1599 | ;; when the recursion point is in the tail
1600 | ;; position (a return position).
1601 | ;;
1602 | ;; Now in `sum1` and `sum2` we had to add
1603 | ;; another function arity just to keep track
1604 | ;; of the `accumulator`. This is very
1605 | ;; common in recursion, while recurring
1606 | ;; you have to keep track of some
1607 | ;; accumulated value, therefore Clojure
1608 | ;; makes it simpler by providing another
1609 | ;; form called `loop` which plays well
1610 | ;; with `recur`. In Clojure you'll often
1611 | ;; hear about `loop/recur` construct.
1612 | ;;
1613 | ;; Let's see how we can rewrite the previous
1614 | ;; function to leverage the `loop/recur`
1615 | ;; construct.
1616 |
1617 | (defn sum3
1618 | [num]
1619 | (loop [n num
1620 | accumulator 0]
1621 | (if (< n 1)
1622 | accumulator
1623 | ;; else
1624 | (recur (dec n) (+ n accumulator)))))
1625 | ;;=> #'learn-clojure.basics/sum3
1626 |
1627 | (sum3 10)
1628 | ;;=> 55
1629 |
1630 | ;; Let's see another example with the Fibonacci
1631 | ;; sequence. Let's start with the mundane
1632 | ;; recursion.
1633 |
1634 | (defn fibonacci1
1635 | [n]
1636 | (if (< n 2)
1637 | 1
1638 | ;; else
1639 | (+ (fibonacci1 (- n 1))
1640 | (fibonacci1 (- n 2)))))
1641 | ;;=> #'learn-clojure.basics/fibonacci1
1642 |
1643 | (fibonacci1 1)
1644 | ;;=> 1
1645 |
1646 | (fibonacci1 10)
1647 | ;;=> 89
1648 |
1649 |
1650 | ;;
1651 | ;; Now this is a simple and very functional
1652 | ;; definition of the Fibonacci sequence, however
1653 | ;; it is particularly bad in terms of computational
1654 | ;; complexity. in fact this is `O(2^n)`.
1655 | ;; Let's use the `time` function to
1656 | ;; calculate how much it takes to compute the
1657 | ;; 35th number in the sequence.
1658 | ;;
1659 |
1660 | (time
1661 | (fibonacci1 35))
1662 | ;;=> "Elapsed time: 1806.753129 msecs"
1663 | ;;=> 14930352
1664 |
1665 | ;;
1666 | ;; Let's try to use tail recursion.
1667 | ;; As you will see we have to restructure
1668 | ;; our function to allow the recursion
1669 | ;; to happen in the tail position.
1670 | ;;
1671 |
1672 |
1673 | (defn fibonacci2
1674 | [n]
1675 | (loop [i n c 1 p 1]
1676 | (if (< i 2)
1677 | c
1678 | (recur (dec i) (+' c p) c))))
1679 | ;;=> #'learn-clojure.basics/fibonacci2
1680 |
1681 | (fibonacci2 10)
1682 | ;;=> 89
1683 |
1684 | (time
1685 | (fibonacci2 35))
1686 | ;;=> "Elapsed time: 0.04467 msecs"
1687 | ;;=> 14930352
1688 |
1689 | (time
1690 | (fibonacci2 1000))
1691 | ;;=> "Elapsed time: 1.145227 msecs"
1692 | ;;=> 70330367711422815821835254877183549770181269836358732742604905087154537118196933579742249494562611733487750449241765991088186363265450223647106012053374121273867339111198139373125598767690091902245245323403501N
1693 |
1694 |
1695 | ;;
1696 | ;; #### Function composition and partial functions
1697 | ;;
1698 | ;; We have seen earlier that there are functions
1699 | ;; such as `first`, `second`, `last` and `rest` to
1700 | ;; access respectively the first item of the
1701 | ;; sequence, the second item, the last item and
1702 | ;; the tail of the sequence. These functions can
1703 | ;; be combined to create other functions for
1704 | ;; accessing the third, fourth, fifth and other
1705 | ;; positional items. The following functions are
1706 | ;; an example of how to construct two such
1707 | ;; functions.
1708 |
1709 | (defn third
1710 | [coll]
1711 | (first (rest (rest coll))))
1712 |
1713 | (third '(1 2 3 4 5))
1714 | ;;=> 3
1715 |
1716 | (defn fourth
1717 | [coll]
1718 | (first (rest (rest (rest coll)))))
1719 |
1720 | (fourth '(1 2 3 4 5))
1721 | ;;=> 4
1722 |
1723 | ;; But there is another way. If, like in this
1724 | ;; case, the output of a function can be passed
1725 | ;; directly into the input of the next one as a
1726 | ;; simple pipeline of functions then you can just
1727 | ;; use the `comp` function.
1728 | ;;
1729 | ;; (comp f1 f2 f3 ... fn)
1730 |
1731 | (def third (comp first rest rest))
1732 | (def fourth (comp first rest rest rest))
1733 |
1734 | (third '(1 2 3 4 5))
1735 | ;;=> 3
1736 |
1737 | (fourth '(1 2 3 4 5))
1738 | ;;=> 4
1739 |
1740 | ;; Let's see another example. Let's assume
1741 | ;; we have to write a function which given
1742 | ;; a number it doubles it and subtract 1
1743 | ;; from it. So we can use the `multiplier`
1744 | ;; function we wrote earlier to accomplish
1745 | ;; the first part and the Clojure core `dec`
1746 | ;; to decrement it by one and compose them
1747 | ;; together with `comp`.
1748 |
1749 | (defn multiplier [m]
1750 | (fn [n]
1751 | (* n m)))
1752 |
1753 | (def doubler (multiplier 2))
1754 | (def almost-twice (comp dec doubler))
1755 |
1756 | (almost-twice 5)
1757 | ;;=> 9
1758 |
1759 | (almost-twice 9)
1760 | ;;=> 17
1761 |
1762 | ;;
1763 | ;; Now let's say we want to create a function
1764 | ;; which given a number perform `almost-twice` two
1765 | ;; times.
1766 | ;;
1767 |
1768 | (def almost-twice-twice (comp almost-twice almost-twice))
1769 |
1770 | (almost-twice-twice 5)
1771 | ;;=> 17
1772 |
1773 | (almost-twice-twice 10)
1774 | ;;=> 37
1775 |
1776 | ;; Another way we could have written the `doubler`
1777 | ;; function is by using the partial application of
1778 | ;; the function `*`. In Clojure this is achieved
1779 | ;; via the function `partial`.
1780 | ;;
1781 | ;; (partial f arg1 ... argn)
1782 | ;;
1783 |
1784 | (def doubler (partial * 2))
1785 |
1786 | (doubler 5)
1787 | ;;=> 10
1788 |
1789 | ;; what happens here is that the `partial`
1790 | ;; function returns a function which calls `*`
1791 | ;; with the parameters of the partial and the
1792 | ;; parameter of the final call, all in one call.
1793 | ;;
1794 | ;; Another nice example is using the function
1795 | ;; `format` which takes a format-string and a
1796 | ;; bunch of arguments and formats the string
1797 | ;; accordingly. This is very similar to the C
1798 | ;; `printf` function however Clojure uses the Java
1799 | ;; `String.format` implementation. So we can use
1800 | ;; this to create a function that produces a
1801 | ;; string which contains a zero-padded formatted
1802 | ;; version of the given number.
1803 |
1804 | (def pad0 (partial format "%013d"))
1805 |
1806 | (pad0 43)
1807 | ;;=> "0000000000043"
1808 |
1809 | (pad0 2346765847)
1810 | ;;=> "0002346765847"
1811 |
1812 |
1813 | (def item-location (partial format "Section: %d, Row %d, Shelve: %s"))
1814 |
1815 | (item-location 3 12 "F")
1816 | ;;=> "Section: 3, Row 12, Shelve: F"
1817 |
1818 |
1819 | ;;
1820 | ;;
1821 | ;; ### Vars, namespaces, scope and local bindings
1822 | ;;
1823 | ;; When defining a var using `def` or `defn`
1824 | ;; followed by symbol, the symbol is created
1825 | ;; in the local namespace.
1826 | ;; When starting the REPL in a empty project
1827 | ;; the default namespace is called `user`
1828 | ;; so unless you configure differently
1829 | ;; all your vars will be created there.
1830 | ;;
1831 | ;; Namespaces are like containers in which
1832 | ;; vars live in, but namespaces,
1833 | ;; once defined are **globally accessible**.
1834 | ;; As a consequence when you define a var
1835 | ;; using `def` or `defn` these will be accessible
1836 | ;; globally.
1837 | ;;
1838 | ;; We will use `ns` which create a namespace if
1839 | ;; not present and switch to it, and `in-ns` just
1840 | ;; changes the current namespace. we will see how
1841 | ;; to loads namespaces we need with our processing
1842 | ;; with `require` and how vars are globally
1843 | ;; accessible.
1844 |
1845 |
1846 | (ns user.test.one)
1847 | ;;=> nil
1848 |
1849 | (def my-name "john")
1850 | ;;=> #'user.test.one/my-name
1851 |
1852 | my-name
1853 | ;;=> "john"
1854 |
1855 | (ns user.test.two)
1856 | ;;=> nil
1857 |
1858 | (def my-name "julie")
1859 | ;;=> #'user.test.two/my-name
1860 |
1861 | my-name
1862 | ;;=> "julie"
1863 |
1864 | user.test.one/my-name
1865 | ;;=> "john"
1866 |
1867 | user.test.two/my-name
1868 | ;;=> "julie"
1869 |
1870 | (in-ns 'user.test.one)
1871 | ;;=> #namespace[user.test.one]
1872 |
1873 | my-name
1874 | ;;=> "john"
1875 |
1876 | (ns user.test.one)
1877 | ;;=> nil
1878 |
1879 | (def my-name (clojure.string/upper-case "john"))
1880 | ;;=> #'user.test.one/my-name
1881 |
1882 | my-name
1883 | ;;=> "JOHN"
1884 |
1885 | (ns user.test.one
1886 | (:require [clojure.string :as s]))
1887 | ;;=> nil
1888 |
1889 | (def my-name (s/upper-case "john"))
1890 | ;;=> #'user.test.one/my-name
1891 |
1892 | (ns user.test.one
1893 | (:require [clojure.string :refer [upper-case]]))
1894 | ;;=> nil
1895 |
1896 | (def my-name (upper-case "john"))
1897 | ;;=> #'user.test.one/my-name
1898 |
1899 | my-name
1900 | ;;=> "JOHN"
1901 |
1902 | (ns user.test.one
1903 | (:require [clojure.string :refer [upper-case]])
1904 | (:require [user.test.two :as two]))
1905 | ;;=> nil
1906 |
1907 | (def my-name (upper-case two/my-name))
1908 | ;;=> #'user.test.one/my-name
1909 |
1910 | my-name
1911 | ;;=> "JULIE"
1912 |
1913 | ;;
1914 | ;; The global accessible vars (globals) is one
1915 | ;; level of scoping. If you don't want to have
1916 | ;; globally accessible vars then you have to
1917 | ;; use local bindings.
1918 | ;;
1919 | ;; We already had a glimpse of these while
1920 | ;; defining functions. In fact parameters
1921 | ;; are only visible inside the function:
1922 | ;;
1923 |
1924 | (defn sum
1925 | [v1 v2]
1926 | (+ v1 v2))
1927 |
1928 | ;; In this example `v1` and `v2` are only
1929 | ;; accessible inside the function. Outside might
1930 | ;; be undefined or have a different value:
1931 |
1932 |
1933 | (def v1 "hello")
1934 | (def v2 "world")
1935 |
1936 | (sum 10 25)
1937 | ;;=> 35
1938 |
1939 | v1
1940 | ;;=> "hello"
1941 |
1942 | v2
1943 | ;;=> "world"
1944 |
1945 | ;;
1946 | ;; There is another way to create local binding
1947 | ;; which are valid only inside the s-expr block,
1948 | ;; using `let`. With the let form you can create
1949 | ;; local variable which are visible only inside
1950 | ;; the block.
1951 |
1952 | (let [v1 23
1953 | v2 45]
1954 | ;; inside this block v1 v2 have the values 23 and 45
1955 | (+ v1 v2))
1956 | ;;=> 68
1957 |
1958 | ;;
1959 | ;; outside the block v1 and v2 are resolved in the
1960 | ;; parent scope which in this case is the
1961 | ;; namespace/global You can even nest `let`
1962 | ;; bindings and use them inside functions. Here
1963 | ;; we use `println` to print to the standard
1964 | ;; output a message
1965 |
1966 | (let [v1 "this is a local value"] ;; outer block
1967 | (println "outer-v1:" v1)
1968 |
1969 | (let [v1 1] ;; inner block
1970 | (println "inner-v1:" v1))
1971 |
1972 | (println "after-v1:" v1))
1973 |
1974 | (println "global-v1:" v1) ;; global
1975 |
1976 | ;;=> outer-v1: this is a local value
1977 | ;;=> inner-v1: 1
1978 | ;;=> after-v1: this is a local value
1979 | ;;=> global-v1: hello
1980 |
1981 |
1982 | ;;
1983 | ;; ### Destructuring
1984 | ;;
1985 | ;; Destructuring is a simple, yet powerful feature
1986 | ;; of Clojure. There are several ways in which you
1987 | ;; can leverage destructuring to make your code
1988 | ;; cleaner, with less repetitions, and less
1989 | ;; bug-prone code. Destructuring is a way to
1990 | ;; unpack a collection into values and bind them
1991 | ;; to locals. It takes a bit of exercise to make
1992 | ;; the eye used to read destructuring forms, but
1993 | ;; once done, the code appears much cleaner. I
1994 | ;; won't cover the destructuring here, however I
1995 | ;; wrote a detailed post about the topic which you
1996 | ;; can find here: [The complete guide to Clojure
1997 | ;; destructuring](http://blog.brunobonacci.com/2014/11/16/clojure-complete-guide-to-destructuring/)
1998 | ;;
1999 | ;;
2000 | ;; ### Flow control
2001 | ;;
2002 | ;; We briefly introduced `if` for flow control,
2003 | ;; which is the basic form on top of which all the
2004 | ;; others are based upon. Moreover there are more
2005 | ;; options for flow control in Clojure which we
2006 | ;; will see i.e `if`,`not`, `and`, `or`, `if-not`,
2007 | ;; `when`, `when-not`, `cond` and `case`.
2008 | ;;
2009 | ;;
2010 | ;; (if condition
2011 | ;; then
2012 | ;; else)
2013 | ;;
2014 | ;; the `condition` doesn't have to be a boolean
2015 | ;; expression necessarily as, in Clojure, anything
2016 | ;; is considered to be `true` except `false` and
2017 | ;; `nil` As you would expect if the `condition` is
2018 | ;; evaluated to be true the `then` expression is
2019 | ;; evaluated, otherwise the `else` expression is
2020 | ;; evaluated. The overall result will be
2021 | ;; determined by the result of the expression
2022 | ;; which is evaluated.
2023 | ;;
2024 |
2025 | (if (= 1 1)
2026 | "this is true"
2027 | "this is false")
2028 | ;;=> "this is true"
2029 |
2030 | (if (not (= 1 1))
2031 | "this is true"
2032 | "this is false")
2033 | ;;=> "this is false"
2034 |
2035 | ;;
2036 | ;; Some times you don't have `else` clause,
2037 | ;; so you can omit it.
2038 |
2039 | (if (not= 1 0)
2040 | (println "that's odd"))
2041 | ;;=> that's odd
2042 | ;;=> nil
2043 |
2044 | ;;
2045 | ;; when you have `if` and `not` together you can
2046 | ;; combine them in `if-not`
2047 |
2048 | (if-not (= 1 0)
2049 | (println "that's odd"))
2050 | ;;=> that's odd
2051 | ;;=> nil
2052 |
2053 | ;; But when there is no else expression
2054 | ;; a more idiomatic way to write it in Clojure
2055 | ;; would be to use the form `when`, and similarly
2056 | ;; when you have a negation in your condition
2057 | ;; you can use `when-not`.
2058 |
2059 | (when (not= 1 0)
2060 | (println "that's odd"))
2061 | ;;=> that's odd
2062 | ;;=> nil
2063 |
2064 | (when-not (= 1 0)
2065 | (println "that's odd"))
2066 | ;;=> that's odd
2067 | ;;=> nil
2068 |
2069 | ;;
2070 | ;; `when` accepts more than one expression and the
2071 | ;; result of the overall expression is the result
2072 | ;; of last form, or `nil` if the condition is
2073 | ;; false.
2074 |
2075 | (when true
2076 | 1
2077 | 2
2078 | 3
2079 | 4)
2080 | ;;=> 4
2081 |
2082 | ;;
2083 | ;; However `if` accepts one form for the then, and
2084 | ;; another form for the `else` when given. If you
2085 | ;; have to invoke several functions perhaps with
2086 | ;; side-effect, then you have to use the `do`
2087 | ;; form.
2088 |
2089 | (do
2090 | 1
2091 | 2
2092 | 3
2093 | 4)
2094 | ;;=> 4
2095 |
2096 |
2097 | (if true
2098 | (do
2099 | (println "this is executed when true")
2100 | (println "this one too.")
2101 | (println "the next line is the value returned")
2102 | :ok)
2103 | (do
2104 | (println "this is executed in the else")
2105 | :this-is-else))
2106 | ;;=> this is executed when true
2107 | ;;=> this one too.
2108 | ;;=> the next line is the value returned
2109 | ;;=> :ok
2110 |
2111 |
2112 | ;;
2113 | ;; If you have to check the equality to many
2114 | ;; different values you can use the `case`
2115 | ;; which is similar to `switch/case` of many
2116 | ;; languages. In Clojure it looks like this:
2117 | ;;
2118 | ;; (case value
2119 | ;; val1 expr1
2120 | ;; val2 expr2
2121 | ;; val3 expr3
2122 | ;; default-exp)
2123 | ;;
2124 |
2125 | (let [order-status :completed]
2126 | (case order-status
2127 | :new "We have received your order, thanks."
2128 | :processing "We are processing your order"
2129 | :ready "We are processing your order"
2130 | :shipped "Your order is on it's way"
2131 | :completed "This order has been already delivered"
2132 | "This order is not found"))
2133 | ;;=> "This order has been already delivered"
2134 |
2135 | ;;
2136 | ;; If you have multiple value with the same
2137 | ;; expression you can group them in a list.
2138 | ;;
2139 |
2140 | (let [order-status :ready]
2141 | (case order-status
2142 | :new "We have received your order, thanks."
2143 | (:processing :ready) "We are processing your order"
2144 | :shipped "Your order is on it's way"
2145 | :completed "This order has been already delivered"
2146 | "This order is not found"))
2147 | ;;=> "We are processing your order"
2148 |
2149 |
2150 | ;;
2151 | ;; Another very popular conditional form is
2152 | ;; `cond`, this is used in place of their
2153 | ;; `if/else-if/else-if/else` of other languages.
2154 | ;;
2155 | ;; (cond
2156 | ;; condition1 expr1
2157 | ;; condition2 expr2
2158 | ;; condition3 expr3
2159 | ;; :else default-expr)
2160 | ;;
2161 |
2162 | (let [age 21]
2163 | (cond
2164 | (< age 16) "You are too young to drive"
2165 | (<= 16 age 18) "You can start your driving lessons"
2166 | (>= 100 age 18) "You can drive only if you have got a license"
2167 | :else "Maybe you should let someone else driving."))
2168 | ;;=> "You can drive only if you have got a license"
2169 |
2170 |
2171 | ;;
2172 | ;; If you have complicated conditions you might
2173 | ;; have to combine the conditions logically with `and`,
2174 | ;; `or` and `not`. We've already seen `not` which
2175 | ;; negates the given condition, while `and` and
2176 | ;; `or` work as you would expect.
2177 | ;;
2178 | ;; (and
2179 | ;; condition1
2180 | ;; condition2
2181 | ;; condition3)
2182 | ;;
2183 | ;; the value of the entire expression is the value
2184 | ;; of the last condition. If a condition is found
2185 | ;; to be falsey (`false` or `nil`) the
2186 | ;; evaluation is interrupted and the whole expression
2187 | ;; will have the value of last evaluated expression.
2188 | ;;
2189 |
2190 | (and true true true)
2191 | ;;=> true
2192 |
2193 | (and 1 2 3 4)
2194 | ;;=> 4
2195 |
2196 | (and 1 2 nil 4 5)
2197 | ;;=> nil
2198 |
2199 | ;;
2200 | ;; Similarly `or` accepts multiple conditions,
2201 | ;; and they are evaluated in the given order,
2202 | ;; and the first condition which is found to
2203 | ;; be true will stop the evaluation
2204 | ;; and return its value as the value of the
2205 | ;; the whole expression.
2206 |
2207 | (or false false nil true)
2208 | ;;=> true
2209 |
2210 | (or false 1 nil 3)
2211 | ;;=> 1
2212 |
2213 | ;;
2214 | ;; `or` is often used to provide default
2215 | ;; values to parameters function via destructuring
2216 | ;; however it can be used in normal code as well.
2217 | ;;
2218 |
2219 | (defn connection-url [config-map resource]
2220 | (let [protocol (or (:protocol config-map) "http")
2221 | hostname (or (:hostname config-map) "localhost")
2222 | port (or (:port config-map) 8080)]
2223 | (str protocol "://" hostname ":" port resource )))
2224 |
2225 | (connection-url {} "/users")
2226 | ;;=> "http://localhost:8080/users"
2227 |
2228 | ;;
2229 | ;; Obviously you can combine `and`, `or` and `not`
2230 | ;; to create arbitrary complex conditions.
2231 | ;;
2232 | ;;
2233 | ;; ### Core functions
2234 | ;;
2235 | ;; The core has hundreds of functions defined,
2236 | ;; which all work on the basic data structures
2237 | ;; that we've seen so far. You can find the full list
2238 | ;; in the [Clojure cheatsheet](http://clojure.org/api/cheatsheet)
2239 | ;;
2240 | ;;
2241 | ;; #### The function: `apply`
2242 | ;;
2243 | ;; For the purpose of this course we will
2244 | ;; only see a few examples starting with `apply`.
2245 | ;; As the same suggests, it "applies" a function
2246 | ;; to a given list of arguments.
2247 | ;;
2248 | ;; (apply f args)
2249 | ;; (apply f x args)
2250 | ;;
2251 |
2252 | (def words ["Hello" " " "world!"])
2253 |
2254 | (str ["Hello" " " "world!"])
2255 | ;;=> "[\"Hello\" \" \" \"world!\"]"
2256 |
2257 | (apply str ["Hello" " " "world!"])
2258 | ;;=> "Hello world!"
2259 |
2260 | (apply str "first-argument: " ["Hello" " " "world!"])
2261 | ;;=> "first-argument: Hello world!"
2262 |
2263 | ;;
2264 | ;; #### The function: `map`
2265 | ;;
2266 | ;; Next we will see one of the most used functions
2267 | ;; in the core `map` which has nothing to do with
2268 | ;; the associative maps (data structures) we seen
2269 | ;; before. `map` comes from the set theory and is
2270 | ;; a function which takes a function and a
2271 | ;; sequence of values and applies the function to
2272 | ;; all values in the sequence. It returns a
2273 | ;; lazy-sequence which means that the function
2274 | ;; application is not performed when calling `map`,
2275 | ;; but it will be performed when the result will
2276 | ;; be consumed.
2277 | ;;
2278 | ;; (map f coll)
2279 | ;;
2280 |
2281 | (map clojure.string/upper-case
2282 | ["Hello" "world!"])
2283 | ;;=> ("HELLO" "WORLD!")
2284 |
2285 | ;;
2286 | ;; #### The function: `mapcat`
2287 | ;;
2288 | ;; Sometimes the application of the function `f`
2289 | ;; returns a list of things. In the following
2290 | ;; example, applying the split function to each sentence
2291 | ;; spilts each sentence and returns a list of words.
2292 | ;;
2293 |
2294 | (map #(clojure.string/split % #"\W+")
2295 | ["Lorem ipsum dolor sit amet, consectetur adipiscing elit."
2296 | "Duis vel ante est."
2297 | "Pellentesque habitant morbi tristique"
2298 | "senectus et netus et malesuada fames ac turpis egestas."])
2299 |
2300 | ;;=> (["Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing" "elit"] ["Duis" "vel" "ante" "est"] ["Pellentesque" "habitant" "morbi" "tristique"] ["senectus" "et" "netus" "et" "malesuada" "fames" "ac" "turpis" "egestas"])
2301 |
2302 | ;; application of the split function to a single
2303 | ;; sentence produces a list of words. Consequently
2304 | ;; the application of the function to all
2305 | ;; sentences produces a list of lists. If we
2306 | ;; rather have a single list with all the words we
2307 | ;; then need to concatenate all the sub-lists into
2308 | ;; one. To do so Clojure core has the `concat`
2309 | ;; function which just concatenates multiple lists
2310 | ;; into one.
2311 |
2312 | (concat [0 1 2 3] [:a :b :c] '(d e f))
2313 | ;;=> (0 1 2 3 :a :b :c d e f)
2314 |
2315 | ;; To obtain a single list of all words we just need
2316 | ;; to apply the `concat` function to the `map` result.
2317 |
2318 | (apply concat
2319 | (map #(clojure.string/split % #"\W+")
2320 | ["Lorem ipsum dolor sit amet, consectetur adipiscing elit."
2321 | "Duis vel ante est."
2322 | "Pellentesque habitant morbi tristique"
2323 | "senectus et netus et malesuada fames ac turpis egestas."]))
2324 | ;;=> ("Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing" "elit" "Duis" "vel" "ante" "est" "Pellentesque" "habitant" "morbi" "tristique" "senectus" "et" "netus" "et" "malesuada" "fames" "ac" "turpis" "egestas")
2325 |
2326 | ;;
2327 | ;; This construct is common enough that Clojure has
2328 | ;; a core function that does just this called `mapcat`.
2329 |
2330 | (mapcat #(clojure.string/split % #"\W+")
2331 | ["Lorem ipsum dolor sit amet, consectetur adipiscing elit."
2332 | "Duis vel ante est."
2333 | "Pellentesque habitant morbi tristique"
2334 | "senectus et netus et malesuada fames ac turpis egestas."])
2335 | ;;=> ("Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing" "elit" "Duis" "vel" "ante" "est" "Pellentesque" "habitant" "morbi" "tristique" "senectus" "et" "netus" "et" "malesuada" "fames" "ac" "turpis" "egestas")
2336 |
2337 | ;;
2338 | ;;
2339 | ;; #### The function: `reduce`
2340 | ;;
2341 | ;; Hadoop uses the two concept of `map` and
2342 | ;; `reduce` to perform arbitrary computation on
2343 | ;; large data. Clojure has `reduce` as core
2344 | ;; function as well. While `map` is applied
2345 | ;; one-by-one to all arguments with the objective
2346 | ;; of performing a transformation `reduce` seeks
2347 | ;; to summarize many values into one. For example
2348 | ;; if you want to find the total sum of a list of
2349 | ;; values you can use reduce in the following way.
2350 | ;;
2351 | ;; (reduce f coll)
2352 | ;;
2353 | ;; It can be used with many core functions
2354 | ;; like the arithmetic functions `+`, `*`
2355 | ;; but also with functions like `max` and `min`
2356 | ;; which respectively return the highest and
2357 | ;; the lowest value passed. But they
2358 | ;; can be used with your own functions too.
2359 | ;;
2360 |
2361 | (reduce + [10 15 23 32 43 54 12 11])
2362 | ;;=> 200
2363 |
2364 | (reduce * [10 15 23 32 43 54 12 11])
2365 | ;;=> 33838041600
2366 |
2367 | (reduce max [10 15 23 32 43 54 12 11])
2368 | ;;=> 54
2369 |
2370 | (reduce str ["Hello" " " "world!"])
2371 | ;;=> "Hello world!"
2372 |
2373 |
2374 | ;;
2375 | ;; #### The function: `filter`
2376 | ;;
2377 | ;; The next function in the core is `filter` which
2378 | ;; takes a *predicate function* and a collection
2379 | ;; and returns a lazy-sequence of the items in the
2380 | ;; collection for which the application of the
2381 | ;; function returns a "truthy" value. Predicate
2382 | ;; functions are functions which takes one
2383 | ;; parameter and return a logical true or false.
2384 | ;;
2385 | ;; (filter pred? coll)
2386 | ;;
2387 | ;; For example:
2388 |
2389 | (filter odd? [0 1 2 3 4 5 6 7])
2390 | ;;=> (1 3 5 7)
2391 |
2392 | (filter #(> (count %) 5)
2393 | ["Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing"])
2394 | ;;=> ("consectetur" "adipiscing")
2395 |
2396 | ;;
2397 | ;; `identity` is a function which given a value
2398 | ;; will just return the value.
2399 | ;; This is often used when a function transformation
2400 | ;; is required as parameter, but no transformation is wanted.
2401 | ;; another idiomatic use of it is to remove nil and false
2402 | ;; from a collection.
2403 | ;;
2404 |
2405 | (filter identity
2406 | ["Lorem" "ipsum" nil "sit" nil "consectetur" nil])
2407 | ;;=> ("Lorem" "ipsum" "sit" "consectetur")
2408 |
2409 | ;;
2410 | ;; The function `remove` is the dual of `filter`
2411 | ;; in the sense that is will remove the items
2412 | ;; for which the predicate function returns true.
2413 | ;;
2414 |
2415 | (filter odd? [0 1 2 3 4 5 6 7])
2416 | ;;=> (1 3 5 7)
2417 |
2418 | (remove odd? [0 1 2 3 4 5 6 7])
2419 | ;;=> (0 2 4 6)
2420 |
2421 | ;;
2422 | ;; #### The function: `sort`
2423 | ;;
2424 | ;; `sort` as you would expect returns a sorted
2425 | ;; sequence of the elements in the given collection.
2426 | ;;
2427 | ;; (sort coll)
2428 | ;; (sort comp coll)
2429 | ;;
2430 |
2431 | (sort [8 3 5 2 5 7 9 4 3 1 0])
2432 | ;;=> (0 1 2 3 3 4 5 5 7 8 9)
2433 |
2434 | (sort > [8 3 5 2 5 7 9 4 3 1 0])
2435 | ;;=> (9 8 7 5 5 4 3 3 2 1 0)
2436 |
2437 | (sort-by count
2438 | ["Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing"])
2439 | ;;=> ("sit" "amet" "Lorem" "ipsum" "dolor" "adipiscing" "consectetur")
2440 |
2441 | (sort-by count >
2442 | ["Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing"])
2443 | ;;=> ("consectetur" "adipiscing" "Lorem" "ipsum" "dolor" "amet" "sit")
2444 |
2445 | (sort-by :score >
2446 | [{:user "john1" :score 345}
2447 | {:user "fred3" :score 75}
2448 | {:user "sam2" :score 291}])
2449 | ;;=> ({:user "john1", :score 345} {:user "sam2", :score 291} {:user "fred3", :score 75})
2450 |
2451 | ;;
2452 | ;; A similar function is `sort-by` which accepts a
2453 | ;; function which is applied to the item before the
2454 | ;; comparison.
2455 | ;;
2456 | ;;
2457 | ;; #### The function: `group-by`
2458 | ;;
2459 | ;; Out of the box in Clojure you have a function
2460 | ;; to perform grouping on your data. `group-by`
2461 | ;; accepts a function and a collection and it will
2462 | ;; apply the given function to all items in the
2463 | ;; collection and then group the items using the
2464 | ;; result of the function, i.e items that give the
2465 | ;; same result when the function is applied end up
2466 | ;; in the same group. Each group will be
2467 | ;; associated with it's common function result.
2468 | ;; It returns a map where the key is the group
2469 | ;; common function result, and the value of the
2470 | ;; map is a list of items which belong to that
2471 | ;; group.
2472 |
2473 | (group-by odd? (range 10))
2474 | ;;=> {false [0 2 4 6 8], true [1 3 5 7 9]}
2475 |
2476 |
2477 | (group-by count ["Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing"])
2478 | ;;=> {5 ["Lorem" "ipsum" "dolor"], 3 ["sit"], 4 ["amet"], 11 ["consectetur"], 10 ["adipiscing"]}
2479 |
2480 | (group-by :user-id [{:user-id 1 :uri "/"}
2481 | {:user-id 2 :uri "/foo"}
2482 | {:user-id 1 :uri "/account"}])
2483 | ;;=> {1 [{:user-id 1, :uri "/"} {:user-id 1, :uri "/account"}], 2 [{:user-id 2, :uri "/foo"}]}
2484 |
2485 | ;;
2486 | ;; #### The function: `frequencies`
2487 | ;;
2488 | ;; When looking to count how frequent an item appears
2489 | ;; in a collection for example to compute histograms
2490 | ;; you can use the function called `frequencies`.
2491 | ;;
2492 |
2493 | (frequencies ["john" "fred" "alice" "fred" "jason" "john" "alice" "john"])
2494 | ;;=> {"john" 3, "fred" 2, "alice" 2, "jason" 1}
2495 |
2496 |
2497 | (frequencies [1 2 3 1 2 3 2 3 1 2 3 3 2 3 2 3 4 4])
2498 | ;;=> {1 3, 2 6, 3 7, 4 2}
2499 |
2500 | ;;
2501 | ;;
2502 | ;; #### The function: `partition`
2503 | ;;
2504 | ;; Another interesting group of functions in the Clojure
2505 | ;; core are `partition`, `partition-all`, `partition-by`.
2506 | ;; Here we will see only the first two.
2507 | ;; `partition` chunks the given sequence into
2508 | ;; sub-sequences (lazy) of `n` items each.
2509 | ;;
2510 | ;; (partition n coll)
2511 | ;; (partition n step coll)
2512 | ;;
2513 |
2514 | (partition 3 (range 11))
2515 | ;;=> ((0 1 2) (3 4 5) (6 7 8))
2516 |
2517 | ;; `partition-all` does the same, but it returns
2518 | ;; also chunks of which are incomplete.
2519 |
2520 | (partition-all 3 (range 11))
2521 | ;;=> ((0 1 2) (3 4 5) (6 7 8) (9 10))
2522 |
2523 | ;;
2524 | ;; The `step` parameters tells the function how
2525 | ;; many item has to move forward after every
2526 | ;; chunk. if not given `step` is equal to `n`
2527 |
2528 | (partition 3 1 (range 11))
2529 | ;;=> ((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6) (5 6 7) (6 7 8) (7 8 9) (8 9 10))
2530 |
2531 | (partition 3 5 (range 11))
2532 | ;;=> ((0 1 2) (5 6 7))
2533 |
2534 | ;;
2535 | ;; #### The function: `into`
2536 | ;;
2537 | ;; `into` is used to create a new collection of a
2538 | ;; given type with all items from another
2539 | ;; collection "into" it. Items are conjoined
2540 | ;; using `conj`. It is often used to change the
2541 | ;; type of a collection, or to build a map out of
2542 | ;; key/value pairs.
2543 | ;;
2544 | ;; (into dest source)
2545 | ;;
2546 |
2547 | (into [] '(0 1 2 3 4 5 6 7 8 9))
2548 | ;;=> [0 1 2 3 4 5 6 7 8 9]
2549 |
2550 | (into '() '(0 1 2 3 4 5 6 7 8 9))
2551 | ;;=> (9 8 7 6 5 4 3 2 1 0)
2552 |
2553 | (into (sorted-map) {:b 2, :c 3, :a 1})
2554 | ;;=> {:a 1, :b 2, :c 3}
2555 |
2556 | (into {} [[:a 1] [:b 2] [:c 3]])
2557 | ;;=> {:a 1, :b 2, :c 3}
2558 |
2559 | (map (fn [e] [(first e) (inc (second e))])
2560 | {:a 1, :b 2, :c 3})
2561 | ;;=> ([:a 2] [:b 3] [:c 4])
2562 |
2563 | (into {}
2564 | (map (fn [e] [(first e) (inc (second e))])
2565 | {:a 1, :b 2, :c 3}))
2566 | ;;=> {:a 2, :b 3, :c 4}
2567 |
2568 | ;;
2569 | ;; #### The function: `juxt`
2570 | ;;
2571 | ;; This function takes a set of functions,
2572 | ;; and returns a function which when
2573 | ;; called with a argument returns a vector
2574 | ;; with all the functions applied to the
2575 | ;; argument in the given order.
2576 | ;;
2577 | ;; (juxt f1 f2 f3 ... fn)
2578 | ;;
2579 | ;; it returns a function which is equivalent to:
2580 | ;;
2581 | ;; (fn [x] (vector (f1 x) (f2 x) (f3 x) ...))
2582 | ;;
2583 | ;;
2584 |
2585 | (def string-info
2586 | (juxt identity clojure.string/upper-case count frequencies))
2587 |
2588 | (string-info "Hello World")
2589 | ;;=> ["Hello World" "HELLO WORLD" 11 {\H 1, \e 1, \l 3, \o 2, \space 1, \W 1, \r 1, \d 1}]
2590 |
2591 |
2592 | ;;
2593 | ;; ### Operation with files
2594 | ;;
2595 | ;; To open, read, write files there are wrappers
2596 | ;; from the java machinery for files. However here
2597 | ;; we will only see how to read and write text
2598 | ;; files which are small enough to fit in memory.
2599 | ;;
2600 | ;; To write some text in a file you can use the
2601 | ;; function `spit`, while to read the content of a
2602 | ;; file as a string you can use `slurp`.
2603 | ;;
2604 |
2605 | (spit "/tmp/my-file.txt"
2606 | "This is the content")
2607 | ;;=> nil
2608 |
2609 |
2610 | (slurp "/tmp/my-file.txt")
2611 | ;;=> "This is the content."
2612 |
2613 | ;;
2614 | ;; ### Error handling
2615 | ;;
2616 | ;; What happens if the file you trying to read
2617 | ;; doesn't exists? or the device you trying to
2618 | ;; write to is full? The underlying Java APIs will
2619 | ;; throw an exception. Clojure provides access to
2620 | ;; the java machinery for error handling and you
2621 | ;; can use `try`, `catch`, `finally` and `throw`
2622 | ;; with the same semantic as the Java's ones.
2623 | ;;
2624 | ;; You have to surround the code which might throw
2625 | ;; an exception using a `try` form, then you can
2626 | ;; handle the errors by their native type with a
2627 | ;; `catch` block. Finally is a block that gets
2628 | ;; executed no matter what happen in the try block and
2629 | ;; whether or not an exception is raised. `throw`
2630 | ;; is used to throw an exception from your own code.
2631 |
2632 | (slurp "/this_doesnt_exists.txt")
2633 | ;;=> FileNotFoundException /this_doesnt_exists.txt (No such file or directory)
2634 |
2635 |
2636 | (try
2637 | (slurp "/this_doesnt_exists.txt")
2638 | (catch Exception x
2639 | (println "unable to read file.")
2640 | ""))
2641 | ;;=> unable to read file
2642 | ;;=> ""
2643 |
2644 | ;;
2645 | ;; _Oftentimes while working with network
2646 | ;; requests, you might want to retry a given
2647 | ;; request a number of times before giving up. In
2648 | ;; such cases there is a library called
2649 | ;; [safely](https://github.com/BrunoBonacci/safely)
2650 | ;; which might be handy._
2651 | ;;
2652 | ;;
2653 | ;;
2654 | ;; ### Macros
2655 | ;;
2656 | ;; The macros are function which are executed at
2657 | ;; compile time by the compiler. The take code as
2658 | ;; input, and the output is still code. The code
2659 | ;; is expressed in the same stuff you have seen so
2660 | ;; far: lists, symbols, keywords, vectors, maps
2661 | ;; strings etc and from a user point of view they
2662 | ;; look just like normal Clojure functions
2663 | ;; (almost). It is a great way to extends the
2664 | ;; language to meet your domain needs. However I
2665 | ;; think this is a topic for a more advanced
2666 | ;; course. If you want to learn the basics of the
2667 | ;; macro you can read the following blog post:
2668 | ;;
2669 | ;; [A "dead simple" introduction to Clojure macros.](http://blog.brunobonacci.com/2015/04/19/dead-simple-introduction-to-clojure-macros/)
2670 | ;;
2671 |
--------------------------------------------------------------------------------
/clojure-basics/learn_clojure/basics_simple.clj:
--------------------------------------------------------------------------------
1 | (ns learn-clojure.basics-simple
2 | (:require [clojure.string :as str]))
3 |
4 |
5 | ;; ~~~ Introduction to Clojure programming ~~~
6 | ;;
7 | ;; .okko.
8 | ;; lMMWMMMx
9 | ;; ;N:. ;XMo
10 | ;; x, 0W.
11 | ;; .Wk
12 | ;; xM.
13 | ;; .XMk
14 | ;; KMMM.
15 | ;; .KMMWMd
16 | ;; .XMMW,kW.
17 | ;; KMMM: 'Mo
18 | ;; 0MMMc 0N
19 | ;; 0MMMl ;Md
20 | ;; 0MMMl KM; .d
21 | ;; 0MMMd ,MWo. '0d
22 | ;; 0MMMk :WMMMMMK.
23 | ;; 'llll .:dxd;
24 | ;;
25 | ;; Bruno Bonacci
26 |
27 | ;;
28 | ;; ## Clojure basics
29 | ;;
30 | ;; Clojure basics, ground up, with no assumption
31 | ;; of previous Clojure knowledge (just general
32 | ;; programming).
33 | ;;
34 |
35 | ;; ### The REPL
36 | ;;
37 | ;; REPL stands for Read Eval Print Loop.
38 | ;;
39 | ;; Many languages have REPLs but none allow
40 | ;; for a full range of in-flow development
41 | ;; such as LISP ones.
42 | ;;
43 | ;; Better than TDD, the **REPL Driven Development**
44 | ;; offers the fastest feedback.
45 | ;;
46 | ;;
47 | ;; ### Clojure syntax
48 | ;;
49 | ;; Syntax is based on `s-expressions`
50 | ;; a regular markup language which
51 | ;; gives the power to LISP macro system.
52 | ;;
53 | ;; General format is:
54 | ;; ( funciton arg1 arg2 ... argn )
55 |
56 | ;; The key is `homoiconicity`!!!
57 |
58 | ;;
59 | ;; ### Comments
60 |
61 | ;; this is a valid comment
62 | ;; and will be skipped by the reader
63 |
64 | ;; the next line is logical comment
65 | ;; more line a NO-OP instruction
66 | (comment "something") ; in-line comment
67 |
68 | ;; but it requires to have valid clojure
69 | (comment a : b : c) ; this is BAD
70 |
71 | ;;
72 | ;; ### The function call.
73 | ;;
74 | ;; // java and C++
75 | ;; myObject.myFunction(arg1, arg2, arg3);
76 | ;;
77 | ;; // C
78 | ;; myFunction(myStruct, arg1, arg2, arg3);
79 | ;;
80 | ;; ;; Clojure
81 | ;; (my-function myObject arg1 arg2 arg3)
82 | ;;
83 | ;;
84 | ;; Examples:
85 | ;;
86 | ;; // java
87 | ;; "Hello World!".toLowerCase();
88 | ;;
89 | ;; // C - single char
90 | ;; tolower(*c);
91 | ;; // C - Whole string
92 | ;; for ( ; *c; ++c) *c = tolower(*c);
93 | ;; ^^^^^^^^^^^^^
94 | ;;
95 | ;; ;; Clojure
96 | ;; (lower-case "Hello World!")
97 | ;;
98 |
99 |
100 | ;; ### Simple values
101 | ;;
102 | ;; Al simple values evaluate to themselves.
103 |
104 | true
105 | false
106 |
107 | nil
108 |
109 | 1
110 | -4
111 | 29384756298374652983746528376529837456
112 |
113 | 127 ;;=> 127 ; decimal
114 | 0x7F ;;=> 127 ; hexadecimal
115 | 0177 ;;=> 127 ; octal
116 | 32r3V ;;=> 127 ; base 32
117 | 2r01111111 ;;=> 127 ; binary
118 | 36r3J ;;=> 127 ; base 36
119 |
120 | 36rClojure ;;=> 27432414842
121 | 2r0111001101010001001001 ;;=> 1889353
122 |
123 | ;;
124 | ;; In Clojure there are no operators, in fact `+`,
125 | ;; `-`, `*` and `/` are normal functions.
126 | ;;
127 |
128 | (+ 1 2 3 4 5)
129 |
130 | ;;
131 | ;; You can access static fields by
132 | ;; providing the fully qualified class name
133 | ;; followed by a slash (`/`) and the field name,
134 | ;; for example: `java.lang.Long/MAX_VALUE`.
135 | ;; Numbers can be auto-promoted using appropriate
136 | ;; functions like `+'` and `*'`
137 |
138 | (+ 1 java.lang.Long/MAX_VALUE)
139 | (+' 1 java.lang.Long/MAX_VALUE)
140 | (*' java.lang.Long/MAX_VALUE java.lang.Long/MAX_VALUE)
141 |
142 |
143 | 3.2
144 | (type 3.2)
145 | (type 3.2M)
146 | (+ 0.3 0.3 0.3 0.1 ) ;; floating point
147 | (+ 0.3M 0.3M 0.3M 0.1M) ;; big-decimal
148 |
149 | (/ 1 3)
150 | (type 1/3)
151 | (+ 1/3 1/3 1/3)
152 | (/ 21 6)
153 | (+ 1/3 1/3 1/3 4)
154 |
155 |
156 |
157 | \a ; this is the character 'a'
158 | \A ; this is the character 'A'
159 | \\ ; this is the character '\'
160 | \u0041 ; this is unicode for 'A'
161 | \tab ; this is the tab character
162 | \newline ; this is the newline character
163 | \space ; this is the space character
164 |
165 | \a ;;=> \a
166 | (type \a)
167 |
168 |
169 |
170 | "This is a string"
171 | (type "This is a string")
172 |
173 | "Strings in Clojure
174 | can be multi lines
175 | as well!!"
176 |
177 | ;; java inter-operation
178 | ;; "This is a String".toUpperCase()
179 | (.toUpperCase "This is a String")
180 |
181 | (str "This" " is " "a" " concatenation.")
182 | (str "Number of lines: " 123)
183 |
184 |
185 | ;; ## Conditionals & Flow control
186 | ;;
187 | ;; `truthiness` in Clojure
188 | ;; `nil` and `false` are falsey, everything
189 | ;; else is truthy
190 | ;;
191 | ;; (if condition
192 | ;; then-expr
193 | ;; else-expr)
194 | ;;
195 | ;;
196 | ;; (cond
197 | ;; condition1 expr1
198 | ;; condition2 expr2
199 | ;; condition3 expr3
200 | ;; :else default-expr)
201 | ;;
202 | ;; There are more options for flow control in Clojure
203 | ;; i.e `if`,`not`, `and`, `or`, `if-not`,
204 | ;; `when`, `when-not`, `cond` and `case`.
205 |
206 |
207 | (if true "it's true" "it's false")
208 | (if false "it's true" "it's false")
209 | (if nil "it's true" "it's false")
210 | (if "HELLO" "it's true" "it's false")
211 | (if 1 "it's true" "it's false")
212 |
213 |
214 | ;; ### Keywords
215 | ;;
216 |
217 | :blue
218 |
219 | (type :this-is-a-keyword)
220 |
221 | (keyword "blue")
222 |
223 | (= :blue :blue)
224 | ;;=> true
225 |
226 | (= (str "bl" "ue") (str "bl" "ue"))
227 | (identical? (str "bl" "ue") (str "bl" "ue"))
228 |
229 | (identical? :blue :blue)
230 | (identical? (keyword (str "bl" "ue"))
231 | (keyword (str "bl" "ue")))
232 |
233 |
234 | ;;
235 | ;; ### Collections
236 | ;;
237 | ;; Collections in Clojure are:
238 | ;; - Immutable by default
239 | ;; - Persistent data structures (sharing)
240 | ;; - Just values (like 42)
241 | ;; - Every collection can hold any value
242 |
243 |
244 | ;;
245 | ;; #### Lists
246 | ;;
247 | ;; Clojure has single-linked lists built-in and
248 | ;; like all other Clojure collections are
249 | ;; immutable. Lists guarantee `O(1)` insertion on
250 | ;; the head, `O(n)` traversal and element search.
251 | ;;
252 |
253 | (list 1 2 3 4 5)
254 |
255 | (cons 0 (list 1 2 3 4 5))
256 |
257 | ;; As the output suggest the lists literals in
258 | ;; Clojure are expressed with a sequence of values
259 | ;; surrounded by brackets, which is the same of
260 | ;; the function call. That is the reason why the
261 | ;; following line throws an error.
262 |
263 | (1 2 3 4 5)
264 |
265 | (quote (1 2 3 4 5))
266 | '(1 2 3 4 5)
267 |
268 | '(1 "hi" :test 4/5 \c)
269 |
270 |
271 | ;; you can get the head of the list with the
272 | ;; function `first` and use `rest` or `next` to
273 | ;; get the tail. `count` returns the number of
274 | ;; elements in it. `nth` returns the nth element
275 | ;; of the list, while `last` returns last item in
276 | ;; the list.
277 | ;;
278 |
279 | (first '(1 2 3 4 5))
280 | (rest '(1 2 3 4 5))
281 | (next '(1 2 3 4 5))
282 | (rest '(1))
283 | (next '(1))
284 | (count '(5))
285 | (count '(1 2 3 4 5))
286 |
287 | (nth '(1 2 3 4 5) 0)
288 | (nth '(1 2 3 4 5) 1)
289 | (nth '(1 2 3 4 5) 10)
290 | (nth '(1 2 3 4 5) 10 :not-found)
291 | (last '(1 2 3 4 5))
292 | (last '(1))
293 | (last '())
294 |
295 |
296 | ;;
297 | ;; #### Vectors
298 | ;;
299 | ;; Vectors are collections of values which are
300 | ;; indexed by their position in the vector
301 | ;; (starting from 0) called **index**. Insertion
302 | ;; at the end of the vector is `near O(1)` as well
303 | ;; as retrieval of an element by it's index. The
304 | ;; literals is expressed with a sequence of values
305 | ;; surrounded by square brackets or you can use
306 | ;; the `vector` function to construct one. You
307 | ;; can append an element at the end of the vector
308 | ;; with `conj` and use `get` to retrieve an
309 | ;; element in a specific index. Function such as
310 | ;; `first`, `next` `rest`, `last` and `count` will
311 | ;; work just as fine with Vectors.
312 |
313 | [1 2 3 4 5]
314 | [1 "hi" :test 4/5 \c]
315 | (vector 1 2 3 4 5)
316 | (conj [1 2 3 4 5] 6)
317 | (count [1 2])
318 | (first [:a :b :c])
319 | (get [:a :b :c] 1)
320 | (get [:a :b :c] 10)
321 | (get [:a :b :c] 10 :z)
322 |
323 |
324 | ;; #### Maps
325 | ;;
326 | ;; Maps are associative data structures (often
327 | ;; called dictionaries) which maps keys to their
328 | ;; corresponding value. Maps have a literal form
329 | ;; which can be expressed by any number of
330 | ;; key/value pairs surrounded by curly brackets,
331 | ;; or by using `hash-map` or `array-map`
332 | ;; functions. Hash-maps provides a `near O(1)`
333 | ;; insertion time and `near O(1)` seek time. You
334 | ;; can use `assoc` to "add or overwrite" an new
335 | ;; pair, `dissoc` to "remove" a key and its value,
336 | ;; and use `get` to retrieve the value of a given
337 | ;; key.
338 |
339 | {"jane" "jane@acme.com"
340 | "fred" "fred@acme.com"
341 | "rob" "rob@acme.com"}
342 |
343 | {:a 1, :b 2, :c 3}
344 | (hash-map :a 1, :b 2, :c 3)
345 | (array-map :a 1, :b 2, :c 3)
346 | (assoc {:a 1, :b 2, :c 3} :d 4)
347 | (assoc {:a 1, :b 2, :c 3} :b 10)
348 | (dissoc {:a 1, :b 2, :c 3} :b)
349 | (count {:a 1, :b 2, :c 3})
350 | (get {:a 1, :b 2, :c 3} :a)
351 | (get {:a 1, :b 2, :c 3} :a :not-found)
352 | (get {:a 1, :b 2, :c 3} :ZULU :not-found)
353 |
354 | (:a {:a 1, :b 2, :c 3})
355 |
356 | ;;
357 | ;; #### Sets
358 | ;;
359 | ;; Sets are a type of collection which doesn't
360 | ;; allow for duplicate values. While lists and
361 | ;; vector can have duplicate elements, set
362 | ;; eliminates all duplicates. Clojure has a
363 | ;; literal form for sets which is expressed by a
364 | ;; sequence of values surrounded by `#{
365 | ;; }`. Otherwise you construct a set using the
366 | ;; `set` function. With `conj` you can "add" a
367 | ;; new element to an existing set, and `disj` to
368 | ;; "remove" an element from the set. With
369 | ;; `clojure.set/union`, `clojure.set/difference`
370 | ;; and `clojure.set/intersection` you have typical
371 | ;; sets operations. `count` returns the number of
372 | ;; elements in the set in `O(1)` time.
373 |
374 | #{1 2 4}
375 | #{:a 4 5 :d "hello"}
376 | (type #{:a :z})
377 | (set [:a :b :c])
378 | (conj #{:a :c} :b)
379 | (conj #{:a :c} :c)
380 | (disj #{:a :b :c} :b)
381 | (clojure.set/union #{:a} #{:a :b} #{:c :a})
382 | (clojure.set/difference #{:a :b} #{:c :a})
383 | (clojure.set/intersection #{:a :b} #{:c :a})
384 |
385 |
386 | ;;
387 | ;; ### The sequence abstraction
388 | ;;
389 | ;; One of the most powerful abstraction of
390 | ;; Clojure's data structures is the `sequence`
391 | ;; (`clojure.lang.ISeq`) which all data structure
392 | ;; implements. This interface resembles to a Java
393 | ;; iterator, and it implements methods like
394 | ;; `first()`, `rest()`, `more()` and `cons()`. The
395 | ;; power of this abstraction is that it is general
396 | ;; enough to be used in all data structures
397 | ;; (lists, vectors, maps, sets and even strings
398 | ;; can all produce sequences) and you have loads
399 | ;; of functions which manipulates it. Functions
400 | ;; such as `first`, `rest`, `next` and `last` and
401 | ;; many others such as `reverse`, `shuffle`,
402 | ;; `drop`, `take`, `partition`, `filter` etc are
403 | ;; all built on top of the sequence abstraction.
404 | ;; So if you create your own data-structure and
405 | ;; you implement the four methods of the
406 | ;; `clojure.lang.ISeq` interface you can benefit
407 | ;; from all these function without having to
408 | ;; re-implement them for your specific
409 | ;; data-structure.
410 | ;;
411 |
412 | (first [1 2 3 4])
413 | (take 3 [:a :b :c :d :e])
414 | (shuffle [1 2 3 4])
415 | (shuffle #{1 2 3 4})
416 | (reverse [1 2 3 4])
417 | (last (reverse {:a 1 :b 2 :c 3}))
418 |
419 |
420 | (seq "Hello World!")
421 | (first "Hello")
422 | (rest "Hello")
423 | (count "Hello World!")
424 |
425 | ;;
426 | ;; #### Lazy Sequences
427 | ;;
428 | ;; Some of the sequences produced by the core
429 | ;; library are lazy which means that the entire
430 | ;; collection won't be created (*realised*) all at
431 | ;; once but when the elements are requested.
432 |
433 | (range 5 10)
434 |
435 | ;; _**WARNING!!!** Evaluating this from your REPL
436 | ;; might hang/crash your process_, as it will try
437 | ;; evaluate an infinite lazy sequence all at once.
438 |
439 | (range)
440 |
441 | (take 10 (range))
442 |
443 |
444 | ;;
445 | ;; ### Regular expression patterns
446 | ;;
447 |
448 | #"[\w\d.-]+@[\w\d-.]+\.[\w]+"
449 |
450 |
451 | (type #"[\w\d.-]+@[\w\d-.]+\.[\w]+")
452 |
453 | (re-find #"[0-9]+" "only 123 numbers")
454 | (re-find #"[0-9]+" "no numbers")
455 | (re-find #"[\w\d.-]+@[\w\d-.]+\.[\w]+"
456 | "bob.smith@acme.org")
457 |
458 | (if (re-find #"^[\w\d.-]+@[\w\d-.]+\.[\w]+$"
459 | "bob.smith@acme.org")
460 | "it's an email"
461 | "it's not an email")
462 |
463 |
464 | (re-seq #"[0-9]+" "25, 43, 54, 12, 15, 65")
465 |
466 | (re-pattern "[0-9]{1,3}(\\.[0-9]{1,3}){3}")
467 |
468 | (re-find
469 | (re-pattern "[0-9]{1,3}(\\.[0-9]{1,3}){3}")
470 | "my IP is: 192.168.0.12")
471 |
472 |
473 | ;;
474 | ;; Using `re-matcher`, `re-matches`, `re-groups`
475 | ;; allows you to have fine control over the capturing
476 | ;; groups.
477 |
478 |
479 | ;;
480 | ;; ### Symbols and Vars
481 | ;;
482 | ;; Symbols in Clojure are a way to identify things
483 | ;; in your programs which may have various values
484 | ;; at runtime. Like in a mathematical notation, `x`
485 | ;; is something not known which could assume
486 | ;; several different values. In a programming
487 | ;; context, Clojure symbols are similar to
488 | ;; variables in other languages but not exactly.
489 | ;; In other languages variables are places where
490 | ;; you store information, symbols in Clojure
491 | ;; cannot contain data themselves. Vars in
492 | ;; Clojure are the containers of data (one type
493 | ;; of), and symbols are a way to identify them and
494 | ;; give vars meaningful names for your program.
495 | ;;
496 |
497 | username
498 | 'username
499 |
500 | (symbol "username")
501 | (type (symbol "username"))
502 |
503 | (def username "bruno1")
504 | username
505 |
506 | age ;; undefined var produces error
507 | (def age 21)
508 |
509 | age
510 |
511 | (type 'age)
512 | (type age)
513 |
514 |
515 | (def user {:username "bruno1"
516 | :score 12345
517 | :level 32
518 | :achievements #{:fast-run :precision10
519 | :strategy}})
520 |
521 | user
522 |
523 | (def user nil)
524 |
525 | user
526 |
527 |
528 | ;;
529 | ;; ### Immutability
530 | ;;
531 | ;; All basics data-types in Clojure are immutable,
532 | ;; including the collections. This is a very
533 | ;; important aspect of Clojure approach to
534 | ;; functional programming. In Clojure functions
535 | ;; transform values into new values and values are
536 | ;; just values. Since it is absurd to think of
537 | ;; changing a number (1 is always 1),
538 | ;; composite data structures are treated in the same way.
539 | ;; So functions do not mutate values they just produce new ones.
540 | ;; Like adding `1` to `42` produces `43` but
541 | ;; doesn't really change the number `42` as it keeps on
542 | ;; existing on its own, adding an element to a list will
543 | ;; produce a new list but the old one will still be same
544 | ;; and unmodified.
545 | ;;
546 | ;; The advantage of the immutability is that
547 | ;; values (even deeply nested and complex
548 | ;; structures) can be safely shared across threads
549 | ;; and with function callers without worrying
550 | ;; about unsafe or uncoordinated changes. This
551 | ;; simple constraint makes Clojure programs so
552 | ;; much easier to reason about, as the only way to
553 | ;; produce a new value is via a functional
554 | ;; transformation.
555 | ;;
556 |
557 | (def colours '(:red :green :blue))
558 |
559 | (def new-colours (cons :black colours))
560 |
561 |
562 | new-colours
563 | colours
564 |
565 |
566 | (def user {:username "bruno1"
567 | :score 12345
568 | :level 32})
569 |
570 | (def user' (assoc user :level 33))
571 |
572 | user'
573 | user
574 |
575 | ;;
576 | ;; ### Functions
577 | ;;
578 | ;; So far we have seen how to represent data in
579 | ;; our system, now we will see how to make sense
580 | ;; of this data and how to
581 | ;; extract/process/transform it. The way we
582 | ;; express this in Clojure is via functions.
583 | ;;
584 | ;;
585 |
586 | ;; pure
587 | (+ 1 2 3)
588 |
589 | ;; impure
590 | (rand-int 100)
591 |
592 | ;; (+ 1 1 1) is referentially transparent
593 | (+ 1 2 (+ 1 1 1))
594 |
595 |
596 | ;;
597 | ;; #### Function definition
598 | ;;
599 | ;; To define a function you have to use the
600 | ;; special form `fn` or `defn` with the following
601 | ;; syntax.
602 | ;;
603 | ;; for example if we want to define a function
604 | ;; which increments the input parameters by 1 you
605 | ;; will write something as follow:
606 | ;;
607 | ;; ```
608 | ;; /- fn, special form
609 | ;; / parameter vector, 1 param called `n`
610 | ;; | | body -> expression to evaluate when
611 | ;; | | | this function is called
612 | ;; (fn [n] (+ n 1))
613 | ;; ```
614 | ;;
615 | ;; This is the simplest way to define a function.
616 | ;;
617 | ;; Now to refer to this function in our code we
618 | ;; need to give it a name. We can do so with `def`
619 | ;; as we done earlier.
620 | ;;
621 |
622 | (def plus-one (fn [n] (+ n 1)))
623 | ;;=> #'learn-clojure.basics/plus-one
624 |
625 | (plus-one 10)
626 | ;;=> 11
627 |
628 | (plus-one -42)
629 | ;;=> -41
630 |
631 | ;;
632 | ;; As mentioned earlier, during the evaluation process
633 | ;; the symbol `plus-one` is simply replaced with
634 | ;; its value, in the same way we can replace the
635 | ;; symbol with the function definition and obtain
636 | ;; the same result. So symbols can also refer to
637 | ;; functions.
638 |
639 | ;; Evaluation by substitution model.
640 | (plus-one 10)
641 | ((fn [n] (+ n 1)) 10)
642 | (fn [10] (+ 10 1))
643 | (+ 10 1)
644 | 11
645 |
646 |
647 | ;; def + fn = defn
648 |
649 | (defn plus-one [n]
650 | (+ n 1))
651 |
652 |
653 | (plus-one 1)
654 |
655 |
656 | (defn plus-one
657 | "Returns a number which is one greater than the given `n`."
658 | [n]
659 | (+ n 1))
660 |
661 |
662 | (inc 10)
663 |
664 |
665 | (defn make-ip4
666 | [a b c d]
667 | (clojure.string/join "." [a b c d]))
668 |
669 | (make-ip4 192 168 0 1)
670 |
671 |
672 | (defn make-kebab
673 | [& words]
674 | (clojure.string/join "-" words))
675 |
676 |
677 | (make-kebab "i" "like" "kebab")
678 |
679 |
680 | (defn greet
681 | ([]
682 | "Hey, Stranger!")
683 | ([name]
684 | (str "Hello " name))
685 | ([firstname lastname]
686 | (str "Hi, you must be: " lastname ", " firstname " " lastname))
687 | ([title firstname lastname]
688 | (str "Hello " title " " firstname " " lastname)))
689 |
690 | (greet)
691 | (greet "James")
692 | (greet "James" "Bond")
693 | (greet "Dr" "John H." "Watson")
694 |
695 |
696 | ;;
697 | ;; #### High-order functions
698 | ;;
699 | ;; In Clojure functions are reified constructs,
700 | ;; therefore we can threat them as normal
701 | ;; values. As such functions can be passed as
702 | ;; parameters of function or returned as result of
703 | ;; function call.
704 | ;;
705 |
706 | (defn is-commutative?
707 | [op a b]
708 | (= (op a b) (op b a)))
709 |
710 | (is-commutative? + 3 7)
711 | (is-commutative? / 3 7)
712 |
713 |
714 | ;; function which return a function
715 | (defn multiplier
716 | [m]
717 | (fn [n]
718 | (* n m)))
719 |
720 |
721 | (def doubler (multiplier 2))
722 | (doubler 5)
723 | (doubler 10)
724 |
725 | (def mult-10x (multiplier 10))
726 | (mult-10x 35)
727 |
728 | ;;
729 | ;; #### Lambda functions (Anonymous)
730 | ;;
731 | ;; Oftentimes you want to create a function for a
732 | ;; specific task in a local context. Such
733 | ;; functions don't have any reason to have a
734 | ;; global name as they are meaningful only in that
735 | ;; specific context, in this case you can create
736 | ;; anonymous functions (also called lambda
737 | ;; function) and Clojure has some support to make
738 | ;; this easier. We already seen an example of an
739 | ;; anonymous function with our very first function
740 | ;; example.
741 | ;;
742 |
743 | (fn [n] (+ n 1))
744 |
745 | ((fn [n] (+ n 1)) 10)
746 | ;;=> 11
747 |
748 | #(+ % 1)
749 | (#(+ % 1) 10)
750 |
751 | ;;
752 | ;; In this function the symbol `%` replace the argument
753 | ;; If you have more than one parameter you can denote them as
754 | ;; `%1` (or `%`), `%2`, `%3`, `%4` ...
755 | ;;
756 | ;; for example in our `is-commutative?` function we expect
757 | ;; and operation which accept two arguments:
758 |
759 | (is-commutative? #(+ %1 %2) 9 8)
760 |
761 |
762 | ;;
763 | ;; #### Closures
764 | ;;
765 | ;; Closures (with the `s`) are lambdas which refer
766 | ;; to a context (or values from another context).
767 | ;; These functions are said to be "closing over"
768 | ;; the environment. This means that it can access
769 | ;; parameters and values which are NOT in the
770 | ;; parameters list.
771 | ;;
772 |
773 | ;; Like in our `multiplier` function example, the
774 | ;; returned function is closing over the value `m`
775 | ;; which is not in its parameter list but it is a
776 | ;; parameter of the parent context the
777 | ;; `multiplier` fn. While `n` is a normal
778 | ;; parameter `m` is the value we are "closing
779 | ;; over" providing a context for that function.
780 |
781 | (defn multiplier
782 | [m]
783 | (fn [n]
784 | (* n m)))
785 |
786 |
787 | ;;
788 | ;; #### Recursion
789 | ;;
790 | ;; A recursive function is a function which
791 | ;; calls itself. There are two types of recursion
792 | ;; the mundane recursion and the tail recursion.
793 | ;;
794 | ;; Let's see an example of both with this function
795 | ;; which given a number it calculates the sum of
796 | ;; all natural numbers from 1 to the given
797 | ;; number.
798 |
799 | (defn sum1
800 | ([n]
801 | (sum1 n 0))
802 | ([n accumulator]
803 | (if (< n 1)
804 | accumulator
805 | ;; else
806 | (sum1 (dec n) (+ n accumulator)))))
807 |
808 |
809 | (sum1 1)
810 |
811 | (sum1 3)
812 |
813 | (sum1 10)
814 |
815 | ;;
816 | ;; This type of recursion is called mundane
817 | ;; recursion and every new call it allocates one
818 | ;; new frame on the stack so if you run this with
819 | ;; high enough numbers it will blow your stack.
820 | ;;
821 |
822 | (sum1 10000)
823 | ;;=> java.lang.StackOverflowError
824 |
825 | ;;
826 | ;; Let's see how we can write this
827 | ;; function with a tail recursion using
828 | ;; `recur`.
829 | ;;
830 |
831 | (defn sum2
832 | ([n]
833 | (sum2 n 0))
834 | ([n accumulator]
835 | (if (< n 1)
836 | accumulator
837 | ;; else
838 | (recur (dec n) (+ n accumulator)))))
839 | ;;=> #'learn-clojure.basics/sum2
840 |
841 | (sum2 10)
842 |
843 | (sum2 10000)
844 |
845 | (sum2 1000000)
846 |
847 | (sum2 100000000)
848 |
849 |
850 | ;; Let's see how we can rewrite the previous
851 | ;; function to leverage the `loop/recur`
852 | ;; construct.
853 |
854 | (defn sum3
855 | [num]
856 | (loop [n num
857 | accumulator 0]
858 | (if (< n 1)
859 | accumulator
860 | ;; else
861 | (recur (dec n) (+ n accumulator)))))
862 |
863 |
864 | (sum3 10)
865 |
866 |
867 | ;; Let's see another example with the Fibonacci
868 | ;; sequence. Let's start with the mundane
869 | ;; recursion.
870 |
871 | ;; !!! this is O(2^n)
872 | (defn fibonacci1
873 | [n]
874 | (if (< n 2)
875 | 1
876 | ;; else
877 | (+ (fibonacci1 (- n 1))
878 | (fibonacci1 (- n 2)))))
879 |
880 |
881 | (fibonacci1 1)
882 |
883 | (fibonacci1 10)
884 |
885 |
886 | ;;
887 | ;; Now this is a simple and very functional
888 | ;; definition of the Fibonacci sequence, however
889 | ;; it is particularly bad in terms of computational
890 | ;; complexity. in fact this is `O(2^n)`.
891 | ;; Let's use the `time` function to
892 | ;; calculate how much it takes to compute the
893 | ;; 35th number in the sequence.
894 | ;;
895 |
896 | (time
897 | (fibonacci1 35))
898 |
899 | ;;
900 | ;; Let's try to use tail recursion.
901 | ;; As you will see we have to restructure
902 | ;; our function to allow the recursion
903 | ;; to happen in the tail position.
904 | ;;
905 |
906 |
907 | (defn fibonacci2
908 | [n]
909 | (loop [i n c 1 p 1]
910 | (if (< i 2)
911 | c
912 | (recur (dec i) (+' c p) c))))
913 |
914 | (fibonacci2 10)
915 |
916 |
917 | (time
918 | (fibonacci2 35))
919 |
920 |
921 | (time
922 | (fibonacci2 1000))
923 |
924 |
925 |
926 |
927 | ;;
928 | ;; #### Function composition and partial functions
929 | ;;
930 | ;; We have seen earlier that there are functions
931 | ;; such as `first`, `second`, `last` and `rest` to
932 | ;; access respectively the first item of the
933 | ;; sequence, the second item, the last item and
934 | ;; the tail of the sequence. These functions can
935 | ;; be combined to create other functions for
936 | ;; accessing the third, fourth, fifth and other
937 | ;; positional items. The following functions are
938 | ;; an example of how to construct two such
939 | ;; functions.
940 |
941 | (defn third
942 | [coll]
943 | (first (rest (rest coll))))
944 |
945 | (third '(1 2 3 4 5))
946 | ;;=> 3
947 |
948 | (defn fourth
949 | [coll]
950 | (first (rest (rest (rest coll)))))
951 |
952 | (fourth '(1 2 3 4 5))
953 | ;;=> 4
954 |
955 | ;; But there is another way. If, like in this
956 | ;; case, the output of a function can be passed
957 | ;; directly into the input of the next one as a
958 | ;; simple pipeline of functions then you can just
959 | ;; use the `comp` function.
960 | ;;
961 | ;; (comp f1 f2 f3 ... fn)
962 | ;;
963 | ;; (comp f1 f2 f3) = (f1 (f2 (f3 ,,,)))
964 | ;;
965 | (def third (comp first rest rest))
966 | (def fourth (comp first rest rest rest))
967 |
968 | (third '(1 2 3 4 5))
969 | ;;=> 3
970 |
971 | (fourth '(1 2 3 4 5))
972 | ;;=> 4
973 |
974 | ;; Let's see another example. Let's assume
975 | ;; we have to write a function which given
976 | ;; a number it doubles it and subtract 1
977 | ;; from it. So we can use the `multiplier`
978 | ;; function we wrote earlier to accomplish
979 | ;; the first part and the Clojure core `dec`
980 | ;; to decrement it by one and compose them
981 | ;; together with `comp`.
982 |
983 | (defn multiplier [m]
984 | (fn [n]
985 | (* n m)))
986 |
987 | (def doubler (multiplier 2))
988 | (def almost-twice (comp dec doubler))
989 |
990 | (almost-twice 5)
991 | ;;=> 9
992 |
993 | (almost-twice 9)
994 | ;;=> 17
995 |
996 | ;;
997 | ;; Now let's say we want to create a function
998 | ;; which given a number perform `almost-twice` two
999 | ;; times.
1000 | ;;
1001 |
1002 | (def almost-twice-twice (comp almost-twice almost-twice))
1003 |
1004 | (almost-twice-twice 5)
1005 | ;;=> 17
1006 |
1007 | (almost-twice-twice 10)
1008 | ;;=> 37
1009 |
1010 | ;; Another way we could have written the `doubler`
1011 | ;; function is by using the partial application of
1012 | ;; the function `*`. In Clojure this is achieved
1013 | ;; via the function `partial`.
1014 | ;;
1015 | ;; (partial f arg1 ... argn)
1016 | ;;
1017 |
1018 | (def doubler (partial * 2))
1019 |
1020 | (doubler 5)
1021 | ;;=> 10
1022 |
1023 | ;; what happens here is that the `partial`
1024 | ;; function returns a function which calls `*`
1025 | ;; with the parameters of the partial and the
1026 | ;; parameter of the final call, all in one call.
1027 | ;;
1028 |
1029 |
1030 | ;;
1031 | ;;
1032 | ;; ### Vars, namespaces, scope and local bindings
1033 | ;;
1034 | ;; When defining a var using `def` or `defn`
1035 | ;; followed by symbol, the symbol is created
1036 | ;; in the local namespace.
1037 | ;; When starting the REPL in a empty project
1038 | ;; the default namespace is called `user`
1039 | ;; so unless you configure differently
1040 | ;; all your vars will be created there.
1041 | ;;
1042 | ;; Namespaces are like containers in which
1043 | ;; vars live in, but namespaces,
1044 | ;; once defined are **globally accessible**.
1045 | ;; As a consequence when you define a var
1046 | ;; using `def` or `defn` these will be accessible
1047 | ;; globally.
1048 | ;;
1049 | ;; We will use `ns` which create a namespace if
1050 | ;; not present and switch to it, and `in-ns` just
1051 | ;; changes the current namespace. we will see how
1052 | ;; to loads namespaces we need with our processing
1053 | ;; with `require` and how vars are globally
1054 | ;; accessible.
1055 |
1056 |
1057 | (ns user.test.one)
1058 | ;;=> nil
1059 |
1060 | (def my-name "john")
1061 | ;;=> #'user.test.one/my-name
1062 |
1063 | my-name
1064 | ;;=> "john"
1065 |
1066 | (ns user.test.two)
1067 | ;;=> nil
1068 |
1069 | (def my-name "julie")
1070 | ;;=> #'user.test.two/my-name
1071 |
1072 | my-name
1073 | ;;=> "julie"
1074 |
1075 | user.test.one/my-name
1076 | ;;=> "john"
1077 |
1078 | user.test.two/my-name
1079 | ;;=> "julie"
1080 |
1081 |
1082 | (def my-name (clojure.string/upper-case "john"))
1083 | ;;=> #'user.test.one/my-name
1084 |
1085 | (ns user.test.one
1086 | (:require [clojure.string :as s]))
1087 | ;;=> nil
1088 |
1089 | (def my-name (s/upper-case "john"))
1090 | ;;=> #'user.test.one/my-name
1091 |
1092 | (ns user.test.one
1093 | (:require [clojure.string :refer [upper-case]]))
1094 | ;;=> nil
1095 |
1096 | (def my-name (upper-case "john"))
1097 | ;;=> #'user.test.one/my-name
1098 |
1099 | my-name
1100 | ;;=> "JOHN"
1101 |
1102 | ;;
1103 | ;; The global accessible vars (globals) is one
1104 | ;; level of scoping. If you don't want to have
1105 | ;; globally accessible vars then you have to
1106 | ;; use local bindings.
1107 | ;;
1108 | ;; We already had a glimpse of these while
1109 | ;; defining functions. In fact parameters
1110 | ;; are only visible inside the function:
1111 | ;;
1112 |
1113 | (def v1 1)
1114 | (def v2 2)
1115 |
1116 | (defn sum
1117 | [v1 v2]
1118 | (+ v1 v2))
1119 |
1120 |
1121 | (sum 10 25)
1122 | ;;=> 35
1123 |
1124 | v1
1125 | v2
1126 | ;;
1127 | ;; There is another way to create local binding
1128 | ;; which are valid only inside the s-expr block,
1129 | ;; using `let`. With the let form you can create
1130 | ;; local variable which are visible only inside
1131 | ;; the block.
1132 |
1133 | (let [v1 23
1134 | v2 45]
1135 | ;; inside this block v1 v2 have the values 23 and 45
1136 | (+ v1 v2))
1137 | ;;=> 68
1138 |
1139 | ;;
1140 | ;; outside the block v1 and v2 are resolved in the
1141 | ;; parent scope which in this case is the
1142 | ;; namespace/global You can even nest `let`
1143 | ;; bindings and use them inside functions. Here
1144 | ;; we use `println` to print to the standard
1145 | ;; output a message
1146 |
1147 | (let [v1 "this is a local value"] ;; outer block
1148 | (println "outer-v1:" v1)
1149 |
1150 | (let [v1 1] ;; inner block
1151 | (println "inner-v1:" v1))
1152 |
1153 | (println "after-v1:" v1))
1154 |
1155 | (println "global-v1:" v1) ;; global
1156 |
1157 | ;;=> outer-v1: this is a local value
1158 | ;;=> inner-v1: 1
1159 | ;;=> after-v1: this is a local value
1160 | ;;=> global-v1: hello
1161 |
1162 |
1163 |
1164 | ;;
1165 | ;; ### Core functions
1166 | ;;
1167 | ;; The core has hundreds of functions defined,
1168 | ;; which all work on the basic data structures
1169 | ;; that we've seen so far. You can find the full list
1170 | ;; in the [Clojure cheatsheet](http://clojure.org/api/cheatsheet)
1171 | ;;
1172 | ;;
1173 | ;; #### The function: `apply`
1174 | ;;
1175 | ;; For the purpose of this course we will
1176 | ;; only see a few examples starting with `apply`.
1177 | ;; As the same suggests, it "applies" a function
1178 | ;; to a given list of arguments.
1179 | ;;
1180 | ;; (apply f args)
1181 | ;; (apply f x args)
1182 | ;;
1183 |
1184 | (def words ["Hello" " " "world!"])
1185 |
1186 | (str ["Hello" " " "world!"])
1187 | ;;=> "[\"Hello\" \" \" \"world!\"]"
1188 |
1189 | (apply str ["Hello" " " "world!"])
1190 | ;;=> "Hello world!"
1191 |
1192 | (apply str "first-argument: " ["Hello" " " "world!"])
1193 | ;;=> "first-argument: Hello world!"
1194 |
1195 | ;;
1196 | ;; #### The function: `map`
1197 | ;;
1198 | ;; Next we will see one of the most used functions
1199 | ;; in the core `map` which has nothing to do with
1200 | ;; the associative maps (data structures) we seen
1201 | ;; before. `map` comes from the set theory and is
1202 | ;; a function which takes a function and a
1203 | ;; sequence of values and applies the function to
1204 | ;; all values in the sequence. It returns a
1205 | ;; lazy-sequence which means that the function
1206 | ;; application is not performed when calling `map`,
1207 | ;; but it will be performed when the result will
1208 | ;; be consumed.
1209 | ;;
1210 | ;; (map f coll)
1211 | ;;
1212 |
1213 | (map clojure.string/upper-case
1214 | ["Hello" "world!"])
1215 | ;;=> ("HELLO" "WORLD!")
1216 |
1217 | ;;
1218 | ;; #### The function: `mapcat`
1219 | ;;
1220 | ;; Sometimes the application of the function `f`
1221 | ;; returns a list of things. In the following
1222 | ;; example, applying the split function to each sentence
1223 | ;; spilts each sentence and returns a list of words.
1224 | ;;
1225 |
1226 | (map #(clojure.string/split % #"\W+")
1227 | ["Lorem ipsum dolor sit amet, consectetur adipiscing elit."
1228 | "Duis vel ante est."
1229 | "Pellentesque habitant morbi tristique"
1230 | "senectus et netus et malesuada fames ac turpis egestas."])
1231 |
1232 |
1233 | ;; application of the split function to a single
1234 | ;; sentence produces a list of words. Consequently
1235 | ;; the application of the function to all
1236 | ;; sentences produces a list of lists. If we
1237 | ;; rather have a single list with all the words we
1238 | ;; then need to concatenate all the sub-lists into
1239 | ;; one. To do so Clojure core has the `concat`
1240 | ;; function which just concatenates multiple lists
1241 | ;; into one.
1242 |
1243 | (concat [0 1 2 3] [:a :b :c] '(d e f))
1244 | ;;=> (0 1 2 3 :a :b :c d e f)
1245 |
1246 | ;; To obtain a single list of all words we just need
1247 | ;; to apply the `concat` function to the `map` result.
1248 |
1249 | (apply concat
1250 | (map #(clojure.string/split % #"\W+")
1251 | ["Lorem ipsum dolor sit amet, consectetur adipiscing elit."
1252 | "Duis vel ante est."
1253 | "Pellentesque habitant morbi tristique"
1254 | "senectus et netus et malesuada fames ac turpis egestas."]))
1255 | ;;=> ("Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing" "elit" "Duis" "vel" "ante" "est" "Pellentesque" "habitant" "morbi" "tristique" "senectus" "et" "netus" "et" "malesuada" "fames" "ac" "turpis" "egestas")
1256 |
1257 | ;;
1258 | ;; This construct is common enough that Clojure has
1259 | ;; a core function that does just this called `mapcat`.
1260 |
1261 | (mapcat #(clojure.string/split % #"\W+")
1262 | ["Lorem ipsum dolor sit amet, consectetur adipiscing elit."
1263 | "Duis vel ante est."
1264 | "Pellentesque habitant morbi tristique"
1265 | "senectus et netus et malesuada fames ac turpis egestas."])
1266 | ;;=> ("Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing" "elit" "Duis" "vel" "ante" "est" "Pellentesque" "habitant" "morbi" "tristique" "senectus" "et" "netus" "et" "malesuada" "fames" "ac" "turpis" "egestas")
1267 |
1268 | ;;
1269 | ;;
1270 | ;; #### The function: `reduce`
1271 | ;;
1272 | ;; Hadoop uses the two concept of `map` and
1273 | ;; `reduce` to perform arbitrary computation on
1274 | ;; large data. Clojure has `reduce` as core
1275 | ;; function as well. While `map` is applied
1276 | ;; one-by-one to all arguments with the objective
1277 | ;; of performing a transformation `reduce` seeks
1278 | ;; to summarize many values into one. For example
1279 | ;; if you want to find the total sum of a list of
1280 | ;; values you can use reduce in the following way.
1281 | ;;
1282 | ;; (reduce f coll)
1283 | ;;
1284 | ;; It can be used with many core functions
1285 | ;; like the arithmetic functions `+`, `*`
1286 | ;; but also with functions like `max` and `min`
1287 | ;; which respectively return the highest and
1288 | ;; the lowest value passed. But they
1289 | ;; can be used with your own functions too.
1290 | ;;
1291 |
1292 | (reduce + [10 15 23 32 43 54 12 11])
1293 | ;;=> 200
1294 |
1295 | (reduce * [10 15 23 32 43 54 12 11])
1296 | ;;=> 33838041600
1297 |
1298 | (reduce max [10 15 23 32 43 54 12 11])
1299 | ;;=> 54
1300 |
1301 | (reduce str ["Hello" " " "world!"])
1302 | ;;=> "Hello world!"
1303 |
1304 |
1305 | ;;
1306 | ;; #### The function: `filter`
1307 | ;;
1308 | ;; The next function in the core is `filter` which
1309 | ;; takes a *predicate function* and a collection
1310 | ;; and returns a lazy-sequence of the items in the
1311 | ;; collection for which the application of the
1312 | ;; function returns a "truthy" value. Predicate
1313 | ;; functions are functions which takes one
1314 | ;; parameter and return a logical true or false.
1315 | ;;
1316 | ;; (filter pred? coll)
1317 | ;;
1318 | ;; For example:
1319 |
1320 | (filter odd? [0 1 2 3 4 5 6 7])
1321 | ;;=> (1 3 5 7)
1322 |
1323 | (filter #(> (count %) 5)
1324 | ["Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing"])
1325 | ;;=> ("consectetur" "adipiscing")
1326 |
1327 | ;;
1328 | ;; `identity` is a function which given a value
1329 | ;; will just return the value.
1330 | ;; This is often used when a function transformation
1331 | ;; is required as parameter, but no transformation is wanted.
1332 | ;; another idiomatic use of it is to remove nil and false
1333 | ;; from a collection.
1334 | ;;
1335 |
1336 | (filter identity
1337 | ["Lorem" "ipsum" nil "sit" nil "consectetur" nil])
1338 | ;;=> ("Lorem" "ipsum" "sit" "consectetur")
1339 |
1340 | ;;
1341 | ;; The function `remove` is the dual of `filter`
1342 | ;; in the sense that is will remove the items
1343 | ;; for which the predicate function returns true.
1344 | ;;
1345 |
1346 | (filter odd? [0 1 2 3 4 5 6 7])
1347 | ;;=> (1 3 5 7)
1348 |
1349 | (remove odd? [0 1 2 3 4 5 6 7])
1350 | ;;=> (0 2 4 6)
1351 |
1352 | ;;
1353 | ;; #### The function: `sort`
1354 | ;;
1355 | ;; `sort` as you would expect returns a sorted
1356 | ;; sequence of the elements in the given collection.
1357 | ;;
1358 | ;; (sort coll)
1359 | ;; (sort comp coll)
1360 | ;;
1361 |
1362 | (sort [8 3 5 2 5 7 9 4 3 1 0])
1363 | ;;=> (0 1 2 3 3 4 5 5 7 8 9)
1364 |
1365 | (sort > [8 3 5 2 5 7 9 4 3 1 0])
1366 | ;;=> (9 8 7 5 5 4 3 3 2 1 0)
1367 |
1368 | (sort-by count
1369 | ["Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing"])
1370 | ;;=> ("sit" "amet" "Lorem" "ipsum" "dolor" "adipiscing" "consectetur")
1371 |
1372 | (sort-by count >
1373 | ["Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing"])
1374 | ;;=> ("consectetur" "adipiscing" "Lorem" "ipsum" "dolor" "amet" "sit")
1375 |
1376 | (sort-by :score >
1377 | [{:user "john1" :score 345}
1378 | {:user "fred3" :score 75}
1379 | {:user "sam2" :score 291}])
1380 | ;;=> ({:user "john1", :score 345} {:user "sam2", :score 291} {:user "fred3", :score 75})
1381 |
1382 | ;;
1383 | ;; A similar function is `sort-by` which accepts a
1384 | ;; function which is applied to the item before the
1385 | ;; comparison.
1386 | ;;
1387 | ;;
1388 | ;; #### The function: `group-by`
1389 | ;;
1390 | ;; Out of the box in Clojure you have a function
1391 | ;; to perform grouping on your data. `group-by`
1392 | ;; accepts a function and a collection and it will
1393 | ;; apply the given function to all items in the
1394 | ;; collection and then group the items using the
1395 | ;; result of the function, i.e items that give the
1396 | ;; same result when the function is applied end up
1397 | ;; in the same group. Each group will be
1398 | ;; associated with it's common function result.
1399 | ;; It returns a map where the key is the group
1400 | ;; common function result, and the value of the
1401 | ;; map is a list of items which belong to that
1402 | ;; group.
1403 |
1404 | (group-by odd? (range 10))
1405 | ;;=> {false [0 2 4 6 8], true [1 3 5 7 9]}
1406 |
1407 |
1408 | (group-by count ["Lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing"])
1409 | ;;=> {5 ["Lorem" "ipsum" "dolor"], 3 ["sit"], 4 ["amet"], 11 ["consectetur"], 10 ["adipiscing"]}
1410 |
1411 | (group-by :user-id [{:user-id 1 :uri "/"}
1412 | {:user-id 2 :uri "/foo"}
1413 | {:user-id 1 :uri "/account"}])
1414 | ;;=> {1 [{:user-id 1, :uri "/"} {:user-id 1, :uri "/account"}], 2 [{:user-id 2, :uri "/foo"}]}
1415 |
1416 | ;;
1417 | ;; #### The function: `frequencies`
1418 | ;;
1419 | ;; When looking to count how frequent an item appears
1420 | ;; in a collection for example to compute histograms
1421 | ;; you can use the function called `frequencies`.
1422 | ;;
1423 |
1424 | (frequencies ["john" "fred" "alice" "fred" "jason" "john" "alice" "john"])
1425 | ;;=> {"john" 3, "fred" 2, "alice" 2, "jason" 1}
1426 |
1427 |
1428 | (frequencies [1 2 3 1 2 3 2 3 1 2 3 3 2 3 2 3 4 4])
1429 | ;;=> {1 3, 2 6, 3 7, 4 2}
1430 |
1431 | ;;
1432 | ;;
1433 | ;; #### The function: `partition`
1434 | ;;
1435 | ;; Another interesting group of functions in the Clojure
1436 | ;; core are `partition`, `partition-all`, `partition-by`.
1437 | ;; Here we will see only the first two.
1438 | ;; `partition` chunks the given sequence into
1439 | ;; sub-sequences (lazy) of `n` items each.
1440 | ;;
1441 | ;; (partition n coll)
1442 | ;; (partition n step coll)
1443 | ;;
1444 |
1445 | (partition 3 (range 11))
1446 | ;;=> ((0 1 2) (3 4 5) (6 7 8))
1447 |
1448 | ;; `partition-all` does the same, but it returns
1449 | ;; also chunks of which are incomplete.
1450 |
1451 | (partition-all 3 (range 11))
1452 | ;;=> ((0 1 2) (3 4 5) (6 7 8) (9 10))
1453 |
1454 | ;;
1455 | ;; The `step` parameters tells the function how
1456 | ;; many item has to move forward after every
1457 | ;; chunk. if not given `step` is equal to `n`
1458 |
1459 | (partition 3 1 (range 11))
1460 | ;;=> ((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6) (5 6 7) (6 7 8) (7 8 9) (8 9 10))
1461 |
1462 | (partition 3 5 (range 11))
1463 | ;;=> ((0 1 2) (5 6 7))
1464 |
1465 | ;;
1466 | ;; #### The function: `into`
1467 | ;;
1468 | ;; `into` is used to create a new collection of a
1469 | ;; given type with all items from another
1470 | ;; collection "into" it. Items are conjoined
1471 | ;; using `conj`. It is often used to change the
1472 | ;; type of a collection, or to build a map out of
1473 | ;; key/value pairs.
1474 | ;;
1475 | ;; (into dest source)
1476 | ;;
1477 |
1478 | (into [] '(0 1 2 3 4 5 6 7 8 9))
1479 | ;;=> [0 1 2 3 4 5 6 7 8 9]
1480 |
1481 | (into '() '(0 1 2 3 4 5 6 7 8 9))
1482 | ;;=> (9 8 7 6 5 4 3 2 1 0)
1483 |
1484 | (into (sorted-map) {:b 2, :c 3, :a 1})
1485 | ;;=> {:a 1, :b 2, :c 3}
1486 |
1487 | (into {} [[:a 1] [:b 2] [:c 3]])
1488 | ;;=> {:a 1, :b 2, :c 3}
1489 |
1490 | (map (fn [e] [(first e) (inc (second e))])
1491 | {:a 1, :b 2, :c 3})
1492 | ;;=> ([:a 2] [:b 3] [:c 4])
1493 |
1494 | (into {}
1495 | (map (fn [e] [(first e) (inc (second e))])
1496 | {:a 1, :b 2, :c 3}))
1497 | ;;=> {:a 2, :b 3, :c 4}
1498 |
1499 | ;;
1500 |
1501 | ;;
1502 | ;; ### Operation with files
1503 | ;;
1504 | ;; To open, read, write files there are wrappers
1505 | ;; from the java machinery for files. However here
1506 | ;; we will only see how to read and write text
1507 | ;; files which are small enough to fit in memory.
1508 | ;;
1509 | ;; To write some text in a file you can use the
1510 | ;; function `spit`, while to read the content of a
1511 | ;; file as a string you can use `slurp`.
1512 | ;;
1513 |
1514 | (spit "/tmp/my-file.txt"
1515 | "This is the content")
1516 | ;;=> nil
1517 |
1518 |
1519 | (slurp "/tmp/my-file.txt")
1520 | ;;=> "This is the content."
1521 |
1522 | ;;
1523 | ;; ### Error handling
1524 | ;;
1525 | ;; What happens if the file you trying to read
1526 | ;; doesn't exists? or the device you trying to
1527 | ;; write to is full? The underlying Java APIs will
1528 | ;; throw an exception. Clojure provides access to
1529 | ;; the java machinery for error handling and you
1530 | ;; can use `try`, `catch`, `finally` and `throw`
1531 | ;; with the same semantic as the Java's ones.
1532 | ;;
1533 | ;; You have to surround the code which might throw
1534 | ;; an exception using a `try` form, then you can
1535 | ;; handle the errors by their native type with a
1536 | ;; `catch` block. Finally is a block that gets
1537 | ;; executed no matter what happen in the try block and
1538 | ;; whether or not an exception is raised. `throw`
1539 | ;; is used to throw an exception from your own code.
1540 |
1541 | (slurp "/this_doesnt_exists.txt")
1542 | ;;=> FileNotFoundException /this_doesnt_exists.txt (No such file or directory)
1543 |
1544 |
1545 | (try
1546 | (slurp "/this_doesnt_exists.txt")
1547 | (catch Exception x
1548 | (println "unable to read file.")
1549 | ""))
1550 | ;;=> unable to read file
1551 | ;;=> ""
1552 |
1553 | ;;
1554 | ;; ### Destructuring
1555 | ;;
1556 | ;; The complete guide to Clojure destructuring
1557 | ;; http://blog.brunobonacci.com/2014/11/16/clojure-complete-guide-to-destructuring/
1558 | ;;
1559 | ;;
1560 | ;; ### Macros
1561 | ;;
1562 | ;; The macros are function which are executed at
1563 | ;; compile time by the compiler. The take code as
1564 | ;; input, and the output is still code. The code
1565 | ;; is expressed in the same stuff you have seen so
1566 | ;; far: lists, symbols, keywords, vectors, maps
1567 | ;; strings etc and from a user point of view they
1568 | ;; look just like normal Clojure functions
1569 | ;; (almost). It is a great way to extends the
1570 | ;; language to meet your domain needs. However I
1571 | ;; think this is a topic for a more advanced
1572 | ;; course. If you want to learn the basics of the
1573 | ;; macro you can read the following blog post:
1574 | ;;
1575 | ;; A "dead simple" introduction to Clojure macros.
1576 | ;; http://blog.brunobonacci.com/2015/04/19/dead-simple-introduction-to-clojure-macros/
1577 | ;;
1578 |
1579 | (require '[clojure.string :as str])
1580 |
1581 | (into #{} (map str/upper-case (str/split "this is a great language and a great platform" #" ")))
1582 |
1583 |
1584 | (->> (str/split "this is a great language and a great platform" #" ")
1585 | (map str/upper-case)
1586 | (into #{}))
1587 |
1588 |
1589 | (macroexpand
1590 | '(->> (str/split "this is a great language and a great platform" #" ")
1591 | (map str/upper-case)
1592 | (into #{})))
1593 |
1594 |
1595 | ;; can write a macro which turn my expression into a Go-like
1596 | ;; expression which never throws exceptions?
1597 |
1598 |
1599 |
1600 | ;;
1601 |
--------------------------------------------------------------------------------
/clojure-basics/project.clj:
--------------------------------------------------------------------------------
1 | (defproject learn-clojure "0.1.0-SNAPSHOT"
2 | :description "FIXME: write description"
3 | :url "http://example.com/FIXME"
4 | :license {:name "Eclipse Public License"
5 | :url "http://www.eclipse.org/legal/epl-v10.html"}
6 | :dependencies [[org.clojure/clojure "1.10.1"]]
7 | :profiles {:dev {:dependencies [[midje "1.9.9"]]
8 | :plugins [[lein-midje "3.2.2"]]}}
9 | )
10 |
--------------------------------------------------------------------------------
/clojure-basics/src/basics/exercise1.clj:
--------------------------------------------------------------------------------
1 | (ns basics.exercise1
2 | (:require [midje.sweet :refer [fact contains]]
3 | [clojure.string :as str]))
4 |
5 |
6 | ;;
7 | ;; For this exercise we will need some supporting data
8 | ;; Please download the entire Shakespeare opera
9 | ;; from the Gutenberg website
10 | ;; https://www.gutenberg.org/cache/epub/100/pg100.txt
11 | ;; and place the file in your project folder under
12 | ;; ./data/shakespeare.txt
13 | ;;
14 | ;; To objective of this exercise if to find
15 | ;; the top 10 anagram sequences in Shakespeare's
16 | ;; opera.
17 | ;;
18 | ;; An anagram sequence is a group of words which
19 | ;; are made by rearranging the letters
20 | ;; (case-insensitive). For example the words:
21 | ;; "Team", "meat" and "Mate" are all anagram of
22 | ;; each others and belong to the same sequence,
23 | ;; while "eats" and "seat" belong to another
24 | ;; sequence of anagrams.
25 | ;;
26 | ;; Write a function which takes the entire Shakespeare
27 | ;; opera as input which you downloaded as text in
28 | ;; "./data/shakespeare.txt" and returns a sequence
29 | ;; of the longest 10 sequences of anagrams.
30 | ;; Each sequence should not contains duplicates
31 | ;; and should be sorted in alphabetic order.
32 | ;;
33 | ;; Advice: While solving this problem think about
34 | ;; data transformations, rather than state
35 | ;; accumulation.
36 | ;;
37 |
38 |
39 | (defn top-anagrams
40 | [text]
41 | ;; please complete the function
42 | )
43 |
44 |
45 | ;;
46 | ;; Here we are writing a test using the Midje library.
47 | ;; https://github.com/marick/Midje/wiki/A-tutorial-introduction
48 | ;;
49 | ;; Which provides form called `fact` which takes
50 | ;; and expression and it's expected result
51 | ;; in the form of:
52 | ;;
53 | ;; (fact "description"
54 | ;; (+ 1 1) => 2)
55 | ;;
56 | ;;
57 |
58 | (fact "Anagrams are extracted sorted by the longest chain"
59 |
60 | (let [text "My Team's mate eats a lot of meat,
61 | and he never leaves his seat."]
62 |
63 | (top-anagrams text)) => [["mate" "meat" "team"]
64 | ["eats" "seat"]]
65 | )
66 |
67 |
68 |
69 | ;; get the top 10 anagrams chains with
70 | ;; (top-anagrams (slurp "./data/shakespeare.txt"))
71 |
--------------------------------------------------------------------------------
/clojure-basics/src/basics/welcome.clj:
--------------------------------------------------------------------------------
1 | (ns basics.welcome)
2 |
3 | ;; ~~~ Introduction to Clojure programming ~~~
4 | ;;
5 | ;; .okko.
6 | ;; lMMWMMMx
7 | ;; ;N:. ;XMo
8 | ;; x, 0W.
9 | ;; .Wk
10 | ;; xM.
11 | ;; .XMk
12 | ;; KMMM.
13 | ;; .KMMWMd
14 | ;; .XMMW,kW.
15 | ;; KMMM: 'Mo
16 | ;; 0MMMc 0N
17 | ;; 0MMMl ;Md
18 | ;; 0MMMl KM; .d
19 | ;; 0MMMd ,MWo. '0d
20 | ;; 0MMMk :WMMMMMK.
21 | ;; 'llll .:dxd;
22 | ;;
23 | ;; Bruno Bonacci
24 | ;;
25 | ;; Go at the end of the next line and press
26 | ;; Mac OSX: Cmd + Enter
27 | ;; Win/Linux: Control + Enter
28 | ;;
29 | ;; This should evaluate the s-expression.
30 | ;; If you get `2` then your environment is
31 | ;; ready to go, otherwise seek teacher's help.
32 |
33 | (+ 1 1)
34 |
--------------------------------------------------------------------------------