├── 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 | ![CC 4.0](https://i.creativecommons.org/l/by/4.0/80x15.png) 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 | --------------------------------------------------------------------------------