├── .gitignore
├── FUNDING.yml
├── LICENSE
├── README.md
├── clojure
├── README.md
├── basics
│ ├── boolean.clj
│ ├── control-flow.clj
│ ├── define-functions.clj
│ ├── destructuring.clj
│ ├── keywords.clj
│ ├── let.clj
│ ├── namespaces.clj
│ ├── naming-values.clj
│ └── recursion.clj
├── clojure_applied
│ └── model_your_domain
│ │ ├── 1.modeling-entities.clj
│ │ ├── 2.constructing-entities.clj
│ │ └── 3.apollo.clj
├── data_structures
│ ├── atom.clj
│ ├── data-structures.clj
│ ├── hash-map.clj
│ ├── laziness.clj
│ ├── lists.clj
│ ├── persistent-data-structures.clj
│ ├── sets.clj
│ └── vectors.clj
├── functional
│ └── composition.clj
└── functions
│ ├── anonymous-functions.clj
│ ├── comparators.clj
│ ├── core-functions.clj
│ ├── filter.clj
│ ├── function-body.clj
│ ├── functional.clj
│ ├── functions.clj
│ ├── high-order-functions.clj
│ ├── polymorphism.clj
│ ├── reduce.clj
│ └── returning-functions.clj
├── elixir
├── README.md
└── learn-fp-with-elixir
│ ├── 01.thinking-functional
│ ├── 01.immutable_data.ex
│ └── 02.functions.ex
│ ├── 02.variables-and-functions
│ ├── 01.values.ex
│ └── exercises
│ │ ├── 01.ex
│ │ ├── 02.ex
│ │ ├── 03.ex
│ │ └── 04.ex
│ └── 03.using-pattern-matching-to-control-the-program-flow
│ ├── 01.equal_operator.ex
│ └── 02.destructuring.ex
├── haskell
├── README.md
├── basics.hs
└── function_application.hs
├── javascript
├── README.md
├── books
│ ├── composing_software
│ │ ├── README.md
│ │ ├── composing_functions.js
│ │ ├── declarative_programming.js
│ │ ├── functors.js
│ │ └── intro_to_js.js
│ └── mostly_adequate_guide_to_functional_programming
│ │ ├── README.md
│ │ ├── ch02.js
│ │ ├── ch03.js
│ │ └── ch04.js
├── closure.js
├── currying.js
├── first_class_citizens.js
├── function_as_value.js
├── function_composition.js
├── high_order_functions.js
├── immutability
│ ├── avoid_array_mutability.js
│ ├── immutability.js
│ └── slugify.js
├── lazy.js
├── partial_application.js
├── purity_part_1.js
├── purity_part_2.js
├── reduce.js
└── referentially_transparent_function.js
├── programming_challenges
├── 4clojure
│ ├── problem01.clj
│ ├── problem02.clj
│ ├── problem03.clj
│ ├── problem04.clj
│ ├── problem05.clj
│ ├── problem06.clj
│ ├── problem07.clj
│ ├── problem19.clj
│ └── problem20.clj
├── README.md
├── exercism
│ ├── clojure
│ │ ├── armstrong-numbers
│ │ │ ├── .lein-failures
│ │ │ ├── .lein-repl-history
│ │ │ ├── README.md
│ │ │ ├── project.clj
│ │ │ ├── src
│ │ │ │ └── armstrong_numbers.clj
│ │ │ ├── target
│ │ │ │ ├── classes
│ │ │ │ │ └── META-INF
│ │ │ │ │ │ └── maven
│ │ │ │ │ │ └── armstrong-numbers
│ │ │ │ │ │ └── armstrong-numbers
│ │ │ │ │ │ └── pom.properties
│ │ │ │ └── stale
│ │ │ │ │ └── leiningen.core.classpath.extract-native-dependencies
│ │ │ └── test
│ │ │ │ └── armstrong_numbers_test.clj
│ │ ├── hello-world
│ │ │ ├── README.md
│ │ │ ├── project.clj
│ │ │ ├── src
│ │ │ │ └── hello-world.clj
│ │ │ └── test
│ │ │ │ └── hello-world-test.clj
│ │ └── two-fer
│ │ │ ├── .lein-failures
│ │ │ ├── .nrepl-port
│ │ │ ├── README.md
│ │ │ ├── project.clj
│ │ │ ├── src
│ │ │ └── two_fer.clj
│ │ │ ├── target
│ │ │ ├── classes
│ │ │ │ └── META-INF
│ │ │ │ │ └── maven
│ │ │ │ │ └── two-fer
│ │ │ │ │ └── two-fer
│ │ │ │ │ └── pom.properties
│ │ │ ├── repl-port
│ │ │ └── stale
│ │ │ │ └── leiningen.core.classpath.extract-native-dependencies
│ │ │ └── test
│ │ │ └── two_fer_test.clj
│ └── javascript
│ │ ├── collatz-conjecture.js
│ │ ├── gigasecond.js
│ │ ├── hello-world.js
│ │ ├── leap.js
│ │ ├── resistor-color.js
│ │ ├── resistor-colors.js
│ │ ├── reverse-string.js
│ │ ├── triangle.js
│ │ └── two-fer.js
├── hacker_rank
│ ├── array_of_n_elements
│ │ ├── array_of_n_elements.clj
│ │ └── array_of_n_elements_without_range.clj
│ ├── basics
│ │ ├── hello_world.clj
│ │ ├── hello_world_n_times.clj
│ │ └── solve_me_first.clj
│ ├── eval_ex
│ │ └── main.clj
│ ├── fibonacci
│ │ └── fibonacci.js
│ ├── filter_array
│ │ └── filter_array.clj
│ ├── filter_positions_in_a_list
│ │ └── filter_positions_in_a_list.clj
│ ├── list_length
│ │ ├── list_length.clj
│ │ └── list_length_reduce.clj
│ ├── list_replication
│ │ └── list_replication.clj
│ ├── reverse_a_list
│ │ ├── reverse_a_list.clj
│ │ ├── reverse_a_list_into.clj
│ │ └── reverse_a_list_reduce.clj
│ ├── sum_of_odd_elements
│ │ └── sum_of_odd_elements.clj
│ └── update_list
│ │ ├── update_list.clj
│ │ ├── update_list_anonymous.clj
│ │ ├── update_list_map.clj
│ │ └── update_list_map_anonymous.clj
└── playground
│ ├── collisions.clj
│ └── jobs
│ ├── job.clj
│ └── resource
│ ├── input.json
│ └── output.json
├── python
├── README.md
└── intro.py
├── ruby
├── README.md
├── immutable_array.rb
└── immutable_select_with_reduce.rb
└── rust
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .vscode
3 | .exercism
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
--------------------------------------------------------------------------------
/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [imteekay]
2 | custom: [https://teekay.substack.com]
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) TK
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Functional Programming Learning Path
4 |
5 | ## Table of Content
6 |
7 | - [Foundation](#foundation)
8 | - [Why Functional](#why-functional)
9 | - [Advanced Topics](#advanced-topics)
10 | - [Talks](#talks)
11 | - [Books](#books)
12 | - [Declarative Programming](#declarative-programming)
13 | - [Blogs](#blogs)
14 | - [Projects](#projects)
15 | - [Podcasts](#podcasts)
16 | - [Courses](#courses)
17 | - [Lists](#lists)
18 | - [Community](#community)
19 | - [JavaScript](https://github.com/imteekay/functional-programming-learning-path/tree/master/javascript)
20 | - [Rust](https://github.com/imteekay/functional-programming-learning-path/tree/master/rust)
21 | - [Clojure](https://github.com/imteekay/functional-programming-learning-path/tree/master/clojure)
22 | - [Python](https://github.com/imteekay/functional-programming-learning-path/tree/master/python)
23 | - [Ruby](https://github.com/imteekay/functional-programming-learning-path/tree/master/ruby)
24 | - [Programming Challenges](https://github.com/imteekay/functional-programming-learning-path/tree/master/programming_challenges)
25 |
26 | ## Foundation
27 |
28 | - [Functional Programming Learning Path](https://purelyfunctional.tv/learning-paths/functional-programming/)
29 | - [Introduction to Funcional Programming - edX](https://www.edx.org/course/introduction-functional-programming-delftx-fp101x-0)
30 | - [Como programar funcional?](https://www.youtube.com/watch?v=jIYfTKYXJr8)
31 | - [Demystifying functional programming](https://medium.com/building-nubank/demystifying-functional-programming-in-a-real-company-e954a2591504)
32 | - [Programação Funcional para iniciantes](https://medium.com/trainingcenter/programa%C3%A7%C3%A3o-funcional-para-iniciantes-9e2beddb5b43)
33 | - [Awesome Functional Programming](https://github.com/xgrommx/awesome-functional-programming)
34 | - [Functional Programming Jargon](https://github.com/hemanth/functional-programming-jargon)
35 | - [Your functional journey](https://purelyfunctional.tv/guide/your-functional-journey/)
36 | - [The Benefits of Pure Functions](https://alvinalexander.com/scala/fp-book/benefits-of-pure-functions)
37 | - [Pure Functions](https://www.sitepoint.com/functional-programming-pure-functions/)
38 | - [Functional Koans](https://github.com/relevance/functional-koans)
39 | - [Programação funcional, imutabilidade, e previsibilidade](https://mauricioszabo.wordpress.com/2016/03/22/programacao-funcional-imutabilidade-e-previsibilidade/)
40 | - [A practical introduction to functional programming](https://maryrosecook.com/blog/post/a-practical-introduction-to-functional-programming)
41 | - [An introduction to functional programming](https://codewords.recurse.com/issues/one/an-introduction-to-functional-programming)
42 | - [Software Composition](https://medium.com/javascript-scene/composing-software-an-introduction-27b72500d6ea)
43 | - [Functional Education](http://bitemyapp.com/posts/2014-12-31-functional-education.html)
44 | - [What is functional?](https://dev.to/drbearhands/functional-fundamentals-what-is-functional-l66)
45 | - [Types as propositions, programs as proofs](https://dev.to/drbearhands/functional-fundamentals-types-as-propositions-programs-as-proofs-56gh)
46 | - [So You Want to be a Functional Programmer (Part 1)](https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-1-1f15e387e536)
47 | - [So You Want to be a Functional Programmer (Part 2)](https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-2-7005682cec4a)
48 | - [So You Want to be a Functional Programmer (Part 3)](https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-3-1b0fd14eb1a7)
49 | - [So You Want to be a Functional Programmer (Part 4)](https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-4-18fbe3ea9e49)
50 | - [So You Want to be a Functional Programmer (Part 5)](https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-5-c70adc9cf56a)
51 | - [So You Want to be a Functional Programmer (Part 6)](https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-6-db502830403)
52 | - [Friendly Functional Programming](https://functional.works-hub.com/learn/friendly-functional-programming-b3e93)
53 | - [Practical Functional Programming](https://hackernoon.com/practical-functional-programming-6d7932abc58b)
54 | - [Destroy All Ifs](http://degoes.net/articles/destroy-all-ifs)
55 | - [THE PILLARS OF FUNCTIONAL PROGRAMMING (PART 1)](https://sigma.software/about/media/pillars-functional-programming-part-1)
56 | - [Functional Programming Patterns: Cookbook](https://medium.com/@karthikiyengar/functional-programming-patterns-cookbook-3a0dfe2d7e0a)
57 |
58 | ## Higher Order Functions
59 |
60 | - [Getting a handle on Reduce](https://adambard.com/blog/getting-a-handle-on-reduce/)
61 |
62 | ## Immutability
63 |
64 | - [Immutability - something worth striving for](https://dev.to/rwoodnz/immutability---something-worth-striving-for-3ppp)
65 | - [Why shared mutable state is the root of all evil](http://henrikeichenhardt.blogspot.com/2013/06/why-shared-mutable-state-is-root-of-all.html)
66 | - [Immutable data](https://www.sitepoint.com/functional-programming-ruby-value-objects/)
67 | - [Thoughts on Immutability, CI/CD, FP](https://www.infoq.com/podcasts/Vitor-Olivier)
68 |
69 | ## Why Functional
70 |
71 | - [Why functional programming matters](https://hackernoon.com/why-functional-programming-matters-c647f56a7691)
72 | - [Why Functional Programming?](https://purelyfunctional.tv/article/why-functional-programming/)
73 | - [Advantages of Functional Programming](https://blog.codeship.com/advantages-of-functional-programming/)
74 | - [Pros and cons of functional programming](https://itnext.io/pros-and-cons-of-functional-programming-32cdf527e1c2)
75 | - [What are the benefits of functional programming?](https://stackoverflow.com/a/128128/3159162)
76 | - [Benefits of Functional Programming](https://alvinalexander.com/scala/fp-book/benefits-of-functional-programming)
77 | - [Benefits of Functional Programming beyond map/filter/reduce](https://www.youtube.com/watch?v=oaa4XiwEq1E&ab_channel=Jfokus)
78 | - [Benefits of Functional Programming by Example](https://medium.com/@nickmccurdy/benefits-of-functional-programming-by-example-76f1135b0b18)
79 | - [Goodbye, Object Oriented Programming](https://medium.com/@cscalfani/goodbye-object-oriented-programming-a59cda4c0e53)
80 | - [Switching from OOP to Functional Programming](https://medium.com/@olxc/switching-from-oop-to-functional-programming-4187698d4d3)
81 |
82 | ## Advanced Topics
83 |
84 | - [Transducers: Efficient Data Processing Pipelines in JavaScript](https://medium.com/javascript-scene/transducers-efficient-data-processing-pipelines-in-javascript-7985330fe73d)
85 | - [Functors, Monads and better functions](https://dev.to/drbearhands/functors-monads-and-better-functions-26f3)
86 | - [Why Curry Helps](https://hughfdjackson.com/javascript/why-curry-helps/)
87 | - [Curry and Function Composition](https://medium.com/javascript-scene/curry-and-function-composition-2c208d774983)
88 | - [Functional JavaScript: Function Composition For Every Day Use](https://hackernoon.com/javascript-functional-composition-for-every-day-use-22421ef65a10)
89 | - [A Modern Architecture for FP](http://degoes.net/articles/modern-fp)
90 | - [Modern Functional Programming: Part 2](http://degoes.net/articles/modern-fp-part-1)
91 | - [Functional Programming, Abstraction, and Naming Things](http://www.stephendiehl.com/posts/abstraction.html)
92 | - [SOLID: the next step is Functional](http://blog.ploeh.dk/2014/03/10/solid-the-next-step-is-functional/)
93 | - [Functional Design Patterns](https://www.youtube.com/watch?reload=9&v=srQt1NAHYC0&ab_channel=NDCConferences)
94 | - [Free Monads Explained (pt 1)](https://medium.com/@olxc/free-monads-explained-pt-1-a5c45fbdac30)
95 | - [Perpetual Currying in JavaScript](https://medium.com/@paramsingh_66174/perpetual-currying-in-javascript-5ae1c749adc5)
96 |
97 | ## Advanced Topics: Category Theory
98 |
99 | - [From design patterns to category theory by Mark Seemann](http://blog.ploeh.dk/2017/10/04/from-design-patterns-to-category-theory/)
100 |
101 | ## Talks
102 |
103 | - [Functional programming design patterns by Scott Wlaschin](https://www.youtube.com/watch?v=E8I19uA-wGY&ab_channel=IvanPlyusnin)
104 | - [Why Functional Programming Matters by John Hughes](https://www.youtube.com/watch?v=XrNdvWqxBvA&ab_channel=ConfEngine)
105 |
106 | ## Books
107 |
108 | - [How to Design Programs](https://htdp.org/2019-02-24/)
109 | - [Category Theory for Programmers](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/)
110 | - [SICP - Structure and Interpretation
111 | of Computer Programs](https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html)
112 |
113 | ## Declarative Programming
114 |
115 | - [What is declarative programming?](https://stackoverflow.com/a/129639/3159162)
116 | - [Declarative vs Imperative Programming by Ian Mundy](https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2)
117 | - [Imperative vs Declarative Programming by Tyler McGinnis](https://tylermcginnis.com/imperative-vs-declarative-programming/)
118 | - [Imperative versus declarative code… what’s the difference?](https://medium.com/front-end-hacking/imperative-versus-declarative-code-whats-the-difference-adc7dd6c8380)
119 |
120 | ## Blogs
121 |
122 | - [Patterns in Functional Programming](https://patternsinfp.wordpress.com/)
123 | - [Kevin Sookocheff - Functional Programming](https://sookocheff.com/tags/functional-programming/)
124 |
125 | ## Projects
126 |
127 | - [YouTube instant search with FP](https://jaysoo.ca/2016/01/13/functional-programming-little-ideas/)
128 |
129 | ## Podcasts
130 |
131 | - [LambdaCast](https://soundcloud.com/lambda-cast)
132 | - [Programação Funcional com Erick Pintor e Bruno Tavares](http://tecnologicamentearretado.com.br/2014/12/31/programacao-funcional-com-erick-e-bruno/)
133 | - [Programação Funcional com Juliano alves](https://www.tecnoretorica.com.br/2013/04/programacao-funcional/)
134 | - [Programação Funcional - Inviavel Podcast](http://inviavelpodcast.com/10/)
135 | - [CapyCast #10 Linguagens Funcionais Com Marcelo Camargo e Derek Stavis](https://player.fm/series/capycast/capycast-10-linguagens-funcionais-com-marcelo-camargo-e-derek-stavis)
136 | - [The Imposter's Handbook: Functional Programming and Databases](https://www.orbit.fm/bookbytes/17)
137 | - [Functional Programming Languages and the Pursuit of Laziness with Dr. Simon Peyton Jones](https://player.fm/series/microsoft-research-podcast-1910051/ep-056-rerun-functional-programming-languages-and-the-pursuit-of-laziness-with-dr-simon-peyton-jones)
138 |
139 | ## Courses
140 |
141 | - [Functional Programming Principles in Scala](https://www.coursera.org/learn/progfun1)
142 | - [Introduction to Functional Programming](https://www.edx.org/course/introduction-to-functional-programming)
143 |
144 | ## Lists
145 |
146 | - [Awesome Functional Programming by @lucasviola](https://github.com/lucasviola/awesome-functional-programming)
147 | - [Awesome Functional Programming by @xgrommx](https://github.com/xgrommx/awesome-functional-programming)
148 |
149 | ## Community
150 |
151 | - Richard Bird
152 | - Philip Wadler
153 | - Olivier Danvy
154 | - Andrzej Filinski
155 | - Daniel P. Friedman
156 | - Matthias Felleisen
157 | - J. Michael Ashley
158 | - R. Kent Dybvig
159 | - Erik Hilsdale
160 |
161 | ## License
162 |
163 | [MIT](/license) © [TK](https://iamtk.co)
164 |
165 |
166 |
--------------------------------------------------------------------------------
/clojure/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Clojure Resources
4 |
5 | ## Functional Clojure
6 |
7 | - [The Clojure Style Guide](https://github.com/bbatsov/clojure-style-guide)
8 | - [Learning Clojure by Practical.li](http://www.practical.li/clojure)
9 | - [Lambda Island](https://lambdaisland.com/)
10 | - [A Year in Clojure](https://blog.taylorwood.io/2017/09/15/year-behind.html)
11 | - ["Running With Scissors: Live Coding With Data" by Stuart Halloway](https://www.youtube.com/watch?v=Qx0-pViyIDU&feature=youtu.be&ab_channel=StrangeLoop)
12 | - [Learn Clojure in Y minutes](https://learnxinyminutes.com/docs/clojure/)
13 | - [Recursion in Clojure](https://imasters.com.br/desenvolvimento/entendendo-recursividade-com-clojure/)
14 | - [Clojure by example](https://kimh.github.io/clojure-by-example)
15 | - [The Ultimate Guide to Clojure Collections](https://purelyfunctional.tv/guide/clojure-collections/)
16 | - [3 Functional Tools: Map, Filter, and Reduce](https://purelyfunctional.tv/courses/3-functional-tools/)
17 | - [Clojure e simplicidade](https://mauricioszabo.wordpress.com/2016/04/07/clojure-e-simplicidade/)
18 | - [Criação de variáveis e contextos léxicos em Clojure](https://blog.bltavares.com/2015/01/28/criacao-de-variaveis-e-contextos-lexicos-em-clojure/)
19 | - [Stuart Sierra blog](https://stuartsierra.com/writing)
20 | - [Repl](https://lambdaisland.com/guides/clojure-repls)
21 |
22 | ## Advanced FP
23 |
24 | - [Learning Clojure: transducers](https://blog.frankel.ch/learning-clojure/6/)
25 | - [Learning Clojure: the arrow and doto macros](https://blog.frankel.ch/learning-clojure/2/)
26 | - [Decoding Clojure code, getting your feet wet](https://blog.frankel.ch/decoding-clojure-code/)
27 |
28 | ## Clojure API
29 |
30 | - [map with partial](https://practicalli.github.io/clojure/thinking-functionally/map-with-partial.html)
31 | - [The Clojure Style Guide](https://github.com/bbatsov/clojure-style-guide)
32 | - [Cheatsheets and information for Clojure/JVM and ClojureScript](https://github.com/jafingerhut/clojure-cheatsheets)
33 | - [Benchmark programs in Clojure](https://github.com/jafingerhut/clojure-benchmarks)
34 | - [Comparators Guide](https://clojure.org/guides/comparators)
35 | - [Sort by](https://github.com/jafingerhut/thalia/blob/master/doc/project-docs/clojure.core-1.5.1/clojure.core/sort-by.md)
36 | - [Repl Driven Development by Stuart Halloway](https://vimeo.com/223309989)
37 | - [Repl Driven Development by Jay Fields](http://blog.jayfields.com/2014/01/repl-driven-development.html)
38 | - [Clojure Destructuring Tutorial and Cheat Sheet](https://gist.github.com/john2x/e1dca953548bfdfb9844)
39 |
40 | ## Tests
41 |
42 | - [API for clojure.test](https://clojure.github.io/clojure/clojure.test-api.html)
43 | - [deftest](https://clojuredocs.org/clojure.test/deftest)
44 | - [Unit Testing in Functional Programming](https://lispcast.com/unit-testing-in-functional-languages/)
45 | - [Clojure.test Cheatsheet](https://github.com/LeandroTk/learning-functional/blob/master/clojure/tests/clojure.test-cheatsheet.pdf)
46 | - [How we test at Nubank](https://www.youtube.com/watch?v=X_PXoiOIdMs&ab_channel=ClojureDays)
47 | - [Testing in Clojure](https://lambdaisland.com/blog/2018-11-02-test-wars-new-hope)
48 | - [Unit Testing by Daniel Gregoire in Clojure Cookbook](https://github.com/clojure-cookbook/clojure-cookbook/blob/master/10_testing/10-01_unit-testing.asciidoc)
49 |
50 | ## Webapps
51 |
52 | - [Clojure Webapps](https://practicalli.github.io/clojure-webapps/)
53 | - [Compojure](https://github.com/weavejester/compojure)
54 | - [Clojure: A live Demonstration of Simplicity That is Production Ready](https://www.youtube.com/watch?v=LcpbBth7FaQ&ab_channel=WixEngineeringTechTalks)
55 | - [A REST API in Clojure](https://blog.interlinked.org/programming/clojure_rest.html)
56 | - [Building a simple HTTP server in Clojure: Part I — Setting up server](https://medium.com/@divyum/building-a-simple-http-server-in-clojure-b8c80fa5035e)
57 | - [Building a simple HTTP server in Clojure: Part II — Adding routes](https://medium.com/@divyum/building-a-simple-http-server-in-clojure-part-ii-adding-routes-3038a81b625f)
58 | - [Building a simple HTTP server in Clojure: Part III — Dockerizing Clojure Application](https://medium.com/@divyum/building-a-simple-http-server-in-clojure-part-iii-dockerizing-clojure-application-1f53a6a90af2)
59 | - [Clojure for OOP Folks: How to Design Clojure Programs](https://speakerdeck.com/stilkov/clojure-for-oop-folks-how-to-design-clojure-programs)
60 | - [Functional TicTacToe](https://www.youtube.com/watch?v=_eO7EsXO2XE)
61 |
62 | ## Better Software
63 |
64 | - [Clojure Design Patterns](http://mishadoff.com/blog/clojure-design-patterns/)
65 | - [Readable Clojure](http://tonsky.me/blog/readable-clojure/)
66 | - [Validations with Schema](https://camdez.com/blog/2015/08/27/practical-data-coercion-with-prismatic-schema/)
67 | - [Component pattern in Clojure](https://www.youtube.com/watch?v=13cmHf_kt-Q&ab_channel=ClojureTV)
68 | - [Clean Clojure: Meaningful Names](http://ecmendenhall.github.io/blog/blog/2013/09/02/clean-clojure-meaningful-names/)
69 | - [Clean Clojure: Small Functions](http://ecmendenhall.github.io/blog/blog/2013/09/05/clean-clojure-functions/)
70 |
71 | ## Challenges
72 |
73 | - [Clojure challenge](https://github.com/rtaboada/challenge)
74 | - [4Clojure Problems](http://www.4clojure.com/problems)
75 | - [Clojure Koans](http://clojurekoans.com/)
76 | - [Exercism](https://exercism.io/my/tracks/clojure)
77 | - [Hacker Rank Functional Path](https://hackerrank.com/domains/fp)
78 |
79 | ## Books
80 |
81 | - [Clojure Applied](https://www.amazon.com/Clojure-Applied-Practitioner-Ben-Vandgrift/dp/1680500740)
82 | - [Clojure data structures and algorithms cookbook](https://www.amazon.com/Clojure-Data-Structures-Algorithms-Cookbook-ebook/dp/B00YSIM3PU/ref=sr_1_1?s=books&ie=UTF8&qid=1548537151&sr=1-1&keywords=Clojure+data+structures+and+algorithms+cookbook)
83 | - [Clojure in action](https://www.amazon.com/Clojure-Action-Amit-Rathore/dp/1617291528/ref=sr_1_1?s=books&ie=UTF8&qid=1548537165&sr=1-1&keywords=Clojure+in+action)
84 | - [Mastering Clojure Macros](https://www.amazon.com/Mastering-Clojure-Macros-Cleaner-Smarter/dp/1941222226/ref=sr_1_1?s=books&ie=UTF8&qid=1548537179&sr=1-1&keywords=Mastering+Clojure+Macros)
85 | - [Practical Clojure](https://www.amazon.com/Practical-Clojure-Experts-Voice-Source/dp/1430272317/ref=sr_1_2?s=books&ie=UTF8&qid=1548537192&sr=1-2&keywords=Practical+Clojure)
86 | - [The Joy of Clojure](https://www.amazon.com/Joy-Clojure-Michael-Fogus/dp/1617291412/ref=sr_1_1?s=books&ie=UTF8&qid=1548537207&sr=1-1&keywords=The+Joy+of+Clojure)
87 | - [Clojure Cookbook](https://www.amazon.com/Clojure-Cookbook-Recipes-Functional-Programming/dp/1449366171/ref=sr_1_1?s=books&ie=UTF8&qid=1548537215&sr=1-1&keywords=Clojure+Cookbook)
88 |
89 | ## Repositories
90 |
91 | - [Purely Functional Data Structures](https://github.com/leonardoborges/purely-functional-data-structures)
92 | - [Clojure Refactoring](https://github.com/tcrayford/clojure-refactoring)
93 | - [Functional Programming for the Object-Oriented Programmer](https://github.com/marick/fp-oo)
94 |
95 | ## Databases
96 |
97 | - [Learn Datalog Today](http://www.learndatalogtoday.org/)
98 |
99 | ## Twitter to Follow
100 |
101 | - [Lambda Island](https://twitter.com/lambdaisland)
102 | - [Clojurecademy](https://twitter.com/clojurecademy)
103 | - [Planet Clojure](https://twitter.com/planetclojure)
104 | - [Clojure Bridge SP](https://twitter.com/ClojureBridgeSP)
105 | - [Clojure Bridge](https://twitter.com/ClojureBridge)
106 | - [Functional Design in Clojure Podcast](http://twitter.com/@clojuredesign)
107 |
108 |
109 |
--------------------------------------------------------------------------------
/clojure/basics/boolean.clj:
--------------------------------------------------------------------------------
1 | ;; Ask if the value is nil
2 | (nil? nil)
3 | (nil? 1)
4 | (nil? true)
5 | (nil? false)
6 | (nil? "hello")
7 |
8 | ;; nil and false as logical falsiness
9 | (if nil
10 | (println "not going to print")
11 | (println "going to print"))
12 |
13 | (if false
14 | (println "not going to print")
15 | (println "going to print"))
16 |
17 | ;; the rest of the values as truthy
18 | (if "the truthy"
19 | (println "going to print")
20 | (println "not going to print"))
21 |
22 | (if true
23 | (println "going to print")
24 | (println "not going to print"))
25 |
26 | (if 1
27 | (println "going to print")
28 | (println "not going to print"))
29 |
30 | ;; equality operator: =
31 | (= 1 1)
32 | (= nil nil)
33 | (= 1 2)
34 |
35 | ;; boolean operators: "or" and "and"
36 | (or nil false true "string" 1)
37 |
38 | (or (= 1 1) (= "string" "strong"))
39 |
40 | (and nil false true "string" 1)
41 |
42 | (and (= 1 1) (= "string" "strong"))
43 |
--------------------------------------------------------------------------------
/clojure/basics/control-flow.clj:
--------------------------------------------------------------------------------
1 | ;; if-else
2 | (if true "going to return" "not going to return") ;; "going to return"
3 |
4 | (if false "not going to return" "going to return") ;; "going to return"
5 |
6 | (if false "not going to return") ;; nil
7 |
8 | ;; if-do
9 | (if true
10 | (do (println "going to print")
11 | (println "also going to print")
12 | "going to return")
13 | (do (println "not going to print")
14 | "not going to return"))
15 |
16 | ;; if-do
17 | (if false
18 | (do (println "not going to print")
19 | "not going to return")
20 | (do (println "going to print")
21 | (println "also going to print")
22 | "going to return"))
23 |
24 | ;; when
25 | (when true
26 | (println "going to print")
27 | (println "also going to print")
28 | "going to return")
29 |
30 | (when false ;; goint to return nil
31 | (println "going to print")
32 | (println "also going to print")
33 | "going to return")
34 |
--------------------------------------------------------------------------------
/clojure/basics/define-functions.clj:
--------------------------------------------------------------------------------
1 | (defn say-hello
2 | "Just say hello"
3 | [name]
4 | (str "Hello " name))
5 |
6 | (say-hello "TK")
7 |
8 | ; The Docstring: The docstring is a useful way to describe and document your code
9 | (doc map)
10 |
11 | ; Parameters: we can pass zero or more parameters on functions
12 | ; Arity: it is the number of parameters passed on functions
13 | (defn no-parameters
14 | []
15 | "no parameters")
16 |
17 | (no-parameters)
18 |
19 | (defn one-parameter
20 | [a]
21 | (str "only one parameter: " a))
22 |
23 | (one-parameter "one")
24 |
25 | (defn two-parameters
26 | [a b]
27 | (str "now two parameters: " a b))
28 |
29 | (two-parameters 1 2)
30 |
31 | ; arity overloading: a different function body will run depending on the arity
32 | (defn iam
33 | ([name]
34 | (str "I am " name))
35 | ([name hobby]
36 | (str "I am " name " and I like " hobby)))
37 |
38 | (iam "TK")
39 | (iam "TK" "programming")
40 |
41 | ; rest parameters as a list with &
42 | (defn favorite-things
43 | [name & things]
44 | (str "Hey " name ", here are my favorite things: "
45 | (clojure.string/join ", " things)))
46 |
47 | (favorite-things "TK" "code" "run" "read" "eat")
48 |
--------------------------------------------------------------------------------
/clojure/basics/destructuring.clj:
--------------------------------------------------------------------------------
1 | ; bind a name within a collection
2 | (defn my-first
3 | [[first-thing]]
4 | first-thing)
5 |
6 | (my-first [1 2 3])
7 |
8 | ; naming as many elements as you want and also use rest parameters
9 | (defn chooser
10 | [[first-choice second-choice & rest-of-choices]]
11 | (println first-choice)
12 | (println second-choice)
13 | (println (clojure.string/join ", " rest-of-choices)))
14 |
15 | (chooser ["first choice" "second choice" "third choice" "fourth choice"])
16 |
17 | ; destructuring maps
18 | (defn show-treasure-location
19 | [{lat :lat lng :lng}]
20 | (println (str "Lat: " lat))
21 | (println (str "Lng: " lng)))
22 |
23 | (show-treasure-location {:lat 10.22 :lng 90.99})
24 |
--------------------------------------------------------------------------------
/clojure/basics/keywords.clj:
--------------------------------------------------------------------------------
1 | :a
2 | :rumplestiltsken
3 | :34
4 | :_?
5 |
6 | (:a {:a 1 :b 2 :c 3})
7 | (get {:a 1 :b 2 :c 3} :a)
8 | (:d {:a 1 :b 2 :c 3} "default value")
9 |
--------------------------------------------------------------------------------
/clojure/basics/let.clj:
--------------------------------------------------------------------------------
1 | ;; let binds names to value
2 | ;; let it be for this scope
3 |
4 | (let [x 3]
5 | x)
6 |
7 | (def names
8 | ["Tk" "Kazumi" "kaio"])
9 |
10 | (let [adults (take 2 names)]
11 | adults)
12 |
13 | (let [[tk & rest] names]
14 | [tk rest])
15 |
--------------------------------------------------------------------------------
/clojure/basics/namespaces.clj:
--------------------------------------------------------------------------------
1 | ;; creating a def inside the current namespace
2 | (def great-books ["The Effective Engineer" "POP" "Harry Potter"])
3 |
4 | ;; creating namespaces
5 | (create-ns 'cheese-taxonomy)
6 | (in-ns 'cheese-taxonomy)
7 | (ns 'cheese-taxonomy)
8 |
9 | ;; refering to other namespace's objects
10 | (in-ns 'some-namespace)
11 | (def first-thing "Like it")
12 | (def second-thing "Love it")
13 | (in-ns 'other-namespace)
14 |
15 | (clojure.core/refer 'some-namespace)
16 | first-thing
17 | second-thing
18 |
19 | ;; using alias for namespaces
20 | (in-ns 'some.namespace)
21 | (def first-thing "Like it")
22 | (def second-thing "Love it")
23 | (in-ns 'other.namespace)
24 |
25 | (clojure.core/alias 'some 'some.namespace)
26 |
--------------------------------------------------------------------------------
/clojure/basics/naming-values.clj:
--------------------------------------------------------------------------------
1 | ;; We can bind the name (failed-protagonist-names) to a value (vector)
2 | (def failed-protagonist-names
3 | ["Larry Potter" "Doreen the explorer" "the incredible bulk"])
4 |
5 | ;; define a function called error-message
6 | ;; with an argument severity
7 | ;; concatenate a string with one of two other strings
8 | (defn error-message
9 | [severity]
10 | (str "OH GOD! IT'S A DISASTER! WE'RE "
11 | (if (= severity :mild)
12 | "MILDLY INCOVINIENT"
13 | "DOOOOMED!")))
14 |
--------------------------------------------------------------------------------
/clojure/basics/recursion.clj:
--------------------------------------------------------------------------------
1 | (first [1 2 3 4 5]) ;; 1
2 | (rest [1 2 3 4 5]) ;; (2 3 4 5)
3 | (empty? [1 2 3 4 5])
4 | (empty? [])
5 |
6 | ;; I want a function to recursivily print each element of the vector from the start to the end
7 |
8 | (defn recursivily-print
9 | [collection]
10 | (println (first collection))
11 | (if (empty? collection)
12 | (println "no more elements to print")
13 | (recursivily-print (rest collection))))
14 |
15 | (recursivily-print [1 2 3 4 5])
16 |
--------------------------------------------------------------------------------
/clojure/clojure_applied/model_your_domain/1.modeling-entities.clj:
--------------------------------------------------------------------------------
1 | ;; using maps as entities
2 | (def earth {:name "Earth"
3 | :moons 1
4 | :volume 1.08321e12 ;; km^3
5 | :mass 5.97219e24 ;; kg
6 | :aphelion 152098232 ;; km, farthest from sun
7 | :perihelion 147098290 ;; km, closest to sun
8 | :type :Planet ;; entity type
9 | })
10 |
11 | ;; using records as entities
12 | (defrecord Planet [name
13 | moons
14 | volume ;; km^3
15 | mass ;; kg
16 | aphelion ;; km, farthest from sun
17 | perihelion ;; km, closest to sun
18 | ])
19 |
20 | ;; Position factory function
21 | (def earth
22 | (-> Planet "Earth" 1 1.08321e12 5.97219e24 152098232 147098290))
23 |
24 | ;; Map factory function
25 | (def earth
26 | (map->Planet {:name "Earth"
27 | :moons 1
28 | :volume 1.08321e12
29 | :mass 5.97219e24
30 | :aphelion 152098232
31 | :perihelion 147098290))
32 |
--------------------------------------------------------------------------------
/clojure/clojure_applied/model_your_domain/2.constructing-entities.clj:
--------------------------------------------------------------------------------
1 | ;; constructing with options
2 | (defn fn-with-opts [n1 n2 & opts])
3 |
4 | ;; positional destructuring
5 | (defn make-entity [n1 n2 & [n3 n4]])
6 |
7 | ;; implementing a Money value object
8 | (ns ch1.money)
9 |
10 | (declare validate-same-currency)
11 |
12 | (defrecord Currency [divisor sym desc])
13 |
14 | (defrecord Money [amount ^Currency currency]
15 | java.lang.Comparable
16 | (compareTo [m1 m2]
17 | (validate-same-currency m1 m2)
18 | (compare (:amount m1) (:amount m2))))
19 |
20 | (def currencies {:usd (->Currency 100 "USD" "US Dollars")
21 | :eur (->Currency 100 "EUR" "Euro")})
22 |
23 | (defn- validate-same-currency
24 | [m1 m2]
25 | (or (= (:currency m1) (:currency m2))
26 | (throw
27 | (ex-info "Currencies do not match."
28 | {:m1 m1 :m2 m2}))))
29 |
30 | (defn =$
31 | ([m1] true)
32 | ([m1 m2] (zero? (.compareTo m1 m2)))
33 | ([m1 m2 & monies]
34 | (every? zero? (map #(.compareTo m1 %) (conj monies m2)))))
35 |
36 | (defn +$
37 | ([m1] m1)
38 | ([m1 m2]
39 | (validate-same-currency m1 m2)
40 | (->Money (+ (:amount m1) (:amount m2)) (:currency m1)))
41 | ([m1 m2 & monies]
42 | (reduce +$ m1 (conj monies m2))))
43 |
44 | (defn *$ [m n] (->Money (* n (:amount m)) (:currency m)))
45 |
46 | (defn make-money
47 | ([] (make-money 0))
48 | ([amount] (make-money amount :usd))
49 | ([amount currency] (->Money amount currency)))
50 |
51 | (defn -$ [m1 m2 & monies])
52 |
53 | (defn allocate [m proportions])
54 |
55 | (def zero-dollars (make-money 0 :usd))
56 |
57 | (make-money)
58 | (make-money 1)
59 | (make-money 5 (:eur currencies))
--------------------------------------------------------------------------------
/clojure/clojure_applied/model_your_domain/3.apollo.clj:
--------------------------------------------------------------------------------
1 | (ns ch1.apollo)
2 |
3 | ;
4 | (defn make-mission
5 | [name system launched manned? opts]
6 | (let [{:keys [cm-name ;; command module
7 | lm-name ;; lunar module
8 | orbits
9 | evas]} opts]))
10 |
11 | (def apollo-4
12 | (make-mission "Apollo 4"
13 | "Saturn V"
14 | #inst "1967-11-09T12:00:01-00:00"
15 | false
16 | {:orbits 3}))
17 | ;
18 |
19 |
20 | ;
21 | (def mission-defaults {:orbits 0, :evas 0})
22 |
23 | (defn make-mission
24 | [name system launched manned? opts]
25 | (let [{:keys [cm-name ;; command module
26 | lm-name ;; lunar module
27 | orbits
28 | evas]} (merge mission-defaults opts)]))
29 | ;
30 |
31 |
32 | ;
33 | (defn make-mission
34 | [name system launched manned? & opts]
35 | (let [{:keys [cm-name ;; command module
36 | lm-name ;; lunar module
37 | orbits
38 | evas]} opts]))
39 |
40 | (def apollo-4 (make-mission "Apollo 4"
41 | "Saturn V"
42 | #inst "1967-11-09T12:00:01-00:00"
43 | false
44 | :orbits 3))
45 |
46 | (def apollo-11 (make-mission "Apollo 11"
47 | "Saturn V"
48 | #inst "1969-07-16T13:32:00-00:00" true
49 | :cm-name "Columbia"
50 | :lm-name "Eagle"
51 | :orbits 30
52 | :evas 1))
53 | ;
54 |
55 | ;
56 | (defn make-mission
57 | [name system launched manned? & opts]
58 | (let [{:keys [cm-name ;; command module
59 | lm-name ;; lunar module
60 | orbits
61 | evas]
62 | :or {orbits 0, evas 0}} opts] ;; default to 0
63 | ))
64 |
65 | (def apollo-4 (make-mission "Apollo 4"
66 | "Saturn V"
67 | #inst "1967-11-09T12:00:01-00:00"
68 | false
69 | :orbits 3))
70 | ;
71 |
72 | ;
73 | (defn euclidean-norm [ecc-vector])
74 |
75 | (defrecord Planet
76 | [name moons volume mass aphelion perihelion orbital-eccentricity])
77 |
78 | (defn make-planet
79 | "Make a planet from field values and an eccentricity vector"
80 | [name moons volume mass aphelion perhelion ecc-vector]
81 | (->Planet
82 | name moons volume mass aphelion perhelion
83 | (euclidean-norm ecc-vector)))
84 | ;
--------------------------------------------------------------------------------
/clojure/data_structures/atom.clj:
--------------------------------------------------------------------------------
1 | ;; The world is mutable
2 |
3 | (def n (atom 10))
4 |
5 | (swap! n
6 | (fn [old-n] (+ old-n 10)))
7 |
8 | (deref n)
9 |
--------------------------------------------------------------------------------
/clojure/data_structures/data-structures.clj:
--------------------------------------------------------------------------------
1 | ;; numerical
2 | 90
3 | 10.5
4 | 1/5
5 |
6 | ;; strings
7 | "Leandro TK"
8 | "\"Not Leandro TK\""
9 | 'single quote is not a string'
10 |
11 | ;; maps
12 | {}
13 | {:my-key "my string value"}
14 | {"string-key" +} ;; string as key and + function as the value
15 | {:user {:first-name "Leandro" :last-name "TK"}} ;; nested map
16 | (hash-map :a 1 :b 2) ;; using hash-map function to create a new map
17 | (get {:name "TK"} :name) ;; map lookup by key
18 | (get-in {:user {:first-name "Leandro" :last-name "TK"}} [:user :last-name]) ;; map lookup on nested map
19 | ({:name "TK"} :name) ;; treating maps as function to do lookups
20 |
--------------------------------------------------------------------------------
/clojure/data_structures/hash-map.clj:
--------------------------------------------------------------------------------
1 | {:a 1
2 | :b 2
3 | :c 3}
4 |
5 | {:a 1
6 | :a 2} ; throws a exception: keys need to be unique
7 |
8 | ; creating a hash with hash-map function
9 | (hash-map :a 1 :b 2); {:a 1 :b 2}
10 |
11 | ; get value by key
12 | ({:a 1 :b 2} :b) ; 2
13 |
--------------------------------------------------------------------------------
/clojure/data_structures/laziness.clj:
--------------------------------------------------------------------------------
1 | ; Clojure is lazy in the way it handles its sequence types
2 |
3 | (defn if-chain [x y z]
4 | (if x
5 | (if y
6 | (if z
7 | (do
8 | (println "Made it!")
9 | :all-truthy)))))
10 |
11 | (if-chain true true true)
12 |
13 | ; The same implementation but using the `and` macro
14 |
15 | (defn if-chain [x y z]
16 | (and x y z (do (println "Made it!") :all-truthy)))
17 |
18 | (if-chain true true true)
19 | (if-chain () true "String")
20 | (if-chain true false true)
21 |
22 | (defn rec-step [[x & xs]]
23 | (if x
24 | [x (rec-step xs)]
25 | []))
26 |
27 | (rec-step [1 2 3 4])
28 | (rec-step (range 200000)) ;; java.lang.StackOverflowError
29 |
--------------------------------------------------------------------------------
/clojure/data_structures/lists.clj:
--------------------------------------------------------------------------------
1 | '(1 2 3 4 5)
2 | (nth '(1 2 3 4 5) 2)
3 | (nth '(1 2 3 4 5) 4)
4 | (list 1 "two" [1 2 3])
5 | (conj '(2 3 4) 1) ; Add element as the first list item
6 |
--------------------------------------------------------------------------------
/clojure/data_structures/persistent-data-structures.clj:
--------------------------------------------------------------------------------
1 | (defn new-tree [val L R]
2 | {:val val
3 | :L L
4 | :R R})
5 |
6 | (defn build-tree [tree value]
7 | (cond
8 | (nil? tree) {:val value :L nil :R nil}
9 | (< value (:val tree)) (new-tree (:val tree)
10 | (build-tree (:L tree) value)
11 | (:R tree))
12 | :else (new-tree (:val tree)
13 | (:L tree)
14 | (build-tree (:R tree) value))))
15 |
16 | (def tree (build-tree nil 5))
17 | (def tree (build-tree tree 4))
18 | (def tree (build-tree tree 2))
19 | (def tree (build-tree tree 1))
20 | (def tree (build-tree tree 6))
21 |
22 | (defn print-tree [tree]
23 | (when tree
24 | (concat (print-tree (:L tree))
25 | [(:val tree)]
26 | (print-tree (:R tree)))))
27 |
28 | (print-tree tree)
29 |
--------------------------------------------------------------------------------
/clojure/data_structures/sets.clj:
--------------------------------------------------------------------------------
1 | ; unique values
2 | #{"TK" 26 :software-engineer}
3 | (hash-set 1 2 3 4 4 3) ; #{1 2 3 4}
4 | (set [1 2 3 4 1])
5 |
6 | ; do not add a value that already exists in the set
7 | (conj #{1 2 3} 1)
8 |
9 | ; contains? returns true or false
10 | (contains? #{1 2 3} 2)
11 | (contains? #{1 2 3} 0)
12 |
13 | ; get returns the found element (or nil if not found)
14 | (get #{1 2 3} 1)
15 | (get #{1 2 3} 4)
16 |
17 | ; keyword works like the get function
18 | (:1 #{:1 :2 :3})
19 | (:a #{:1 :2 :3})
20 |
--------------------------------------------------------------------------------
/clojure/data_structures/vectors.clj:
--------------------------------------------------------------------------------
1 | ; "syntax"
2 | [1 2 3] ; [1 2 3]
3 |
4 | ; get the first element using index
5 | ([1 2 3] 0) ; 1
6 |
7 | ; get the first element using get
8 | (get [1 2 3] 0) ; 1
9 |
10 | ; get the second element
11 | (get [1 {:first-name "Leandro" :last-name "TK"} 2] 1) ; {:first-name "Leandro" :last-name "TK"}
12 |
13 | ; build a vector from elements
14 | (vector "a" "new" "vector" "of" "strings") ; ["a" "new" "vector" "of" "strings"]
15 |
16 | ; add a new element to the vector
17 | (conj [1 2 3] 4) ; [1 2 3 4]
18 |
19 | ; vectors evaluate each element before building
20 | [1 :x (+ 1 1)] ; [1 :x 2]
21 | ; (eval [1 :x (+ 1 1)])
22 | ; [(eval 1) (eval :x) (eval (+ 1 1))]
23 | ; [1 :x 2]
24 |
--------------------------------------------------------------------------------
/clojure/functional/composition.clj:
--------------------------------------------------------------------------------
1 | (def fifth (comp first rest rest rest rest))
2 |
3 | (fifth [1 2 3 4 5])
4 |
--------------------------------------------------------------------------------
/clojure/functions/anonymous-functions.clj:
--------------------------------------------------------------------------------
1 | ; functions don't need to have names
2 | (fn [params-list]
3 | "something")
4 |
5 | (map (fn [name] (str "Hello " name)) ["TK" "Kazumi" "Kaio"])
6 |
7 | ((fn [n] (* n 2)) 8)
8 |
9 | (#(* % 8) 3)
10 |
11 | (map #(str "Hello " %) ["TK" "Kazumi" "Kaio"])
12 |
--------------------------------------------------------------------------------
/clojure/functions/comparators.clj:
--------------------------------------------------------------------------------
1 | ;; Resource: https://clojure.org/guides/comparators
2 | ;; compare works for many types of values, ordering them in one particular way:
3 | ;; - increasing numeric order for numbers;
4 | ;; - lexicographic order (aka dictionary order) for strings, symbols, and keywords;
5 | ;; - shortest-to-longest order by Clojure vectors, with lexicographic ordering among equal length vectors
6 |
7 | ;; reverse order
8 | (defn reverse-cmp
9 | [a b]
10 | (compare b a))
11 |
12 | (sort reverse-cmp [1 2 3 4])
13 |
14 | ;; using Clojure’s #() notation
15 | (sort #(compare %2 %1) [1 2 3 4])
16 |
17 | ;; Multi-field comparators
18 | (def john1 {:name "John", :salary 35000.00, :company "Acme"})
19 | (def mary {:name "Mary", :salary 35000.00, :company "Mars Inc"})
20 | (def john2 {:name "John", :salary 40000.00, :company "Venus Co"})
21 | (def john3 {:name "John", :salary 30000.00, :company "Asteroids-R-Us"})
22 | (def people [john1 mary john2 john3])
23 |
24 | (defn by-salary-name-company
25 | [x y]
26 | (let [c (compare (:salary y) (:salary x))]
27 | (if (not= c 0)
28 | c
29 | (let [c (compare (:name x) (:name y))]
30 | (if (not= c 0)
31 | c
32 | (compare (:company x) (:company y)))))))
33 |
34 | (sort by-salary-name-company people)
35 |
36 | ;; short verstion of by-salary-name-company
37 | (defn by-salary-name-company
38 | [x y]
39 | (compare [(:salary y) (:name x) (:company x)]
40 | [(:salary x) (:name y) (:company y)]))
41 |
42 | (sort by-salary-name-company people)
43 |
--------------------------------------------------------------------------------
/clojure/functions/core-functions.clj:
--------------------------------------------------------------------------------
1 | ;; Using map as a sequence function for collections
2 |
3 | (defn titleize
4 | [topic]
5 | (str topic " for the Brave and True"))
6 |
7 | (map titleize ["Hamsters" "Ragnarok"])
8 | ; => ("Hamsters for the Brave and True" "Ragnarok for the Brave and True")
9 |
10 | (map titleize '("Empathy" "Decorating"))
11 | ; => ("Empathy for the Brave and True" "Decorating for the Brave and True")
12 |
13 | (map titleize #{"Elbows" "Soap Carving"})
14 | ; => ("Elbows for the Brave and True" "Soap Carving for the Brave and True")
15 |
16 | (map #(titleize (second %)) {:uncomfortable-thing "Winking"})
17 | ; => ("Winking for the Brave and True")
18 |
19 | (defn titleize-hash
20 | [hash]
21 | (titleize (second hash)))
22 |
23 | (map (partial titleize-hash) {:something "Something"
24 | :other-thing "Other"})
25 |
26 | (def human-consumption [8.1 7.3 6.6 5.0])
27 | (def critter-consumption [0.0 0.2 0.3 1.1])
28 | (defn unify-diet-data
29 | [human critter]
30 | {:human human
31 | :critter critter})
32 |
33 | (map unify-diet-data human-consumption critter-consumption)
34 | ; ({:human 8.1, :critter 0.0}
35 | ; {:human 7.3, :critter 0.2}
36 | ; {:human 6.6, :critter 0.3}
37 | ; {:human 5.0, :critter 1.1})
38 |
39 | ; Reduce
40 | (reduce (fn [new-map [key val]]
41 | (assoc new-map key (inc val)))
42 | {}
43 | {:max 30 :min 10})
44 | ; => {:max 31, :min 11}
45 |
46 | ; slugify function
47 |
48 | (defn slugify [text]
49 | (-> text
50 | (clojure.string/trim)
51 | (clojure.string/lower-case)
52 | (clojure.string/replace " " "-")))
53 |
54 | (def text " OLA mundao ")
55 |
56 | (clojure.string/trim text)
57 | (clojure.string/lower-case text)
58 | (clojure.string/replace text " " "-")
59 |
60 | (slugify text)
61 |
--------------------------------------------------------------------------------
/clojure/functions/filter.clj:
--------------------------------------------------------------------------------
1 | ;; (filter f coll) | Clojure Syntax for filter function
2 | ;; Keep just the elements that are true based on the function (predicate) passed
3 |
4 | ;; f = function/predicate
5 | ;; coll = collection
6 |
7 | ;; Some examples:
8 | ;; (filter pasta? pot) ;; strainer
9 | ;; (filter water? pot) ;; coffee
10 | ;; (filter air? house) ;; aircondition
11 |
12 | ;; Using even? function as a filter example
13 | ;; original collection: (0 1 2 3 4 5 6 7 8 9)
14 | ;; result of filter function: (0 2 4 6 8)
15 | (filter even? (range 0 10))
16 |
17 | ;; We can also use keywords as functions for filter
18 | ;; This code will result in: ({:a 1} {:a 2})
19 | ;; (:a {:a 1}) returns 1, and it is true
20 | ;; (:a {:a 2}) returns 2, and it is true
21 | ;; (:a {:b 10}) returns nil, and it is false
22 | ;; (:a {:a false}) returns false, and it is false
23 | (filter :a
24 | [{:a 1}
25 | {:a 2}
26 | {:b 10}
27 | {:a false}])
28 |
29 | ;; (mod x 3): if it is zero, x is divisible by 3
30 | ;; (zero? x): asks if x is zero
31 | ;; (not result): revert the result value. If it is true, it turns to false. Otherwise, true.
32 | ;; In this example, we will filter only the numbers that are not divisible by 3
33 | ;; original collection: (0 1 2 3 4 5 6 7 8 9)
34 | ;; result of filter function: (1 2 4 5 7 8)
35 | (filter
36 | (fn [x] (not (zero? (mod x 3))))
37 | (range 0 10))
38 |
--------------------------------------------------------------------------------
/clojure/functions/function-body.clj:
--------------------------------------------------------------------------------
1 | ; Clojure automatically returns the last form evaluated.
2 | (defn an-example
3 | []
4 | (+ 1 1)
5 | 10
6 | "TK")
7 |
8 | (an-example)
9 |
10 | ; using conditional within a function
11 | (defn number-comment
12 | [number]
13 | (if (> number 5)
14 | (println "greater than five")
15 | (println "less or equal to five")))
16 |
17 | (number-comment 5)
18 | (number-comment 6)
19 |
--------------------------------------------------------------------------------
/clojure/functions/functional.clj:
--------------------------------------------------------------------------------
1 | ;; A pure function: use only the passed parameter
2 | ;; Pure Functions Have No Side Effects
3 | (defn wisdom
4 | [words]
5 | (str words ", Daniel-san"))
6 |
7 | (wisdom "Always bathe on Fridays")
8 |
9 | ;; Not a pure function because it uses an external global object
10 | (def PI 3.14)
11 |
12 | (defn calculate-area
13 | [radius]
14 | (* radius radius PI))
15 |
16 | (calculate-area 10) ;; returns 314.0
17 |
18 | ;; pure function because it uses only parameters passed as arguments
19 | (def PI 3.14)
20 |
21 | (defn calculate-area
22 | [radius, PI]
23 | (* radius radius PI))
24 |
25 | (calculate-area 10 PI) ;; returns 314.0
26 |
27 | ;; Not pure: it uses the global variable and modify the variable
28 | (def counter 1)
29 |
30 | (defn increase-counter
31 | [value]
32 | (def counter (inc value)))
33 |
34 | (increase-counter counter)
35 |
36 | ;; pure function: returns the value increased by 1
37 | (def counter 1)
38 |
39 | (defn increase-counter
40 | [value]
41 | (inc value))
42 |
43 | (increase-counter counter) ;; 2
44 | counter ;; 1
45 |
46 | ;; impure function: reads an external file
47 | (defn characters-counter
48 | [text]
49 | (str "Character count: " (count text)))
50 |
51 | (defn analyze-file
52 | [filename]
53 | (characters-counter (slurp filename)))
54 |
55 | (analyze-file "test.txt")
56 |
57 | ;; using a referentially transparent function, you never have to consider what
58 | ;; possible external conditions could affect the return value of the function.
59 |
60 | ;; immutability
61 |
--------------------------------------------------------------------------------
/clojure/functions/functions.clj:
--------------------------------------------------------------------------------
1 | ; functions syntax: opening parenthesis, operator, operands, closing parenthesis
2 |
3 | ; calling functions
4 | (+ 1 2 3 4 5)
5 | (* 9 9)
6 | (first [1 2 3 4 5])
7 |
8 | ; the return value of "or" function is the first truthy value.
9 | ; In this case, the value returned is the string representation of the plus function
10 | (or + -)
11 |
12 | ; using an expression as an operator of another expression
13 | ((or + -) 1 2 3)
14 |
15 | ; functions that can either take a function as an argument or return a function are called higher-order functions
16 | ; "inc" function increments the value passed
17 | (inc 1.1)
18 |
19 | ; "map" function creates a new list by applying a function to each member of a collection
20 | (map inc [1 2 3 4])
21 |
22 | ; playing with functions within functions
23 | (+ (inc 199) (/ 100 (- 7 2)))
24 |
25 | (zipmap [:a :b :c] [1 2 3]) ; {:a 1 :b 2 :c 3}
26 |
--------------------------------------------------------------------------------
/clojure/functions/high-order-functions.clj:
--------------------------------------------------------------------------------
1 | (map inc [0 1 2 3 4 5])
2 | (range 1 10)
3 | (reduce + (range 1 10))
4 | (reduce + '(1 2 3 4 5 6 7 8 9))
5 | (take 10 (range))
6 | (filter
7 | even?
8 | [0 1 2 3 4 5 6 7 8 9])
9 |
10 | ; function as value --> as arguments
11 |
12 | (def numbers [1 3 2 5 4 6 7])
13 |
14 | (sort numbers) ; (1 2 3 4 5 6 7)
15 | (sort > numbers) ; (7 6 5 4 3 2 1)
16 |
17 | ; sort-by function used to preprocess each sortable element
18 | ; into something that is mutually comparable
19 |
20 | (sort-by second [[:a 2] [:b 7] [:c 3] [:d 6]]) ; ([:a 2] [:c 3] [:d 6] [:b 7])
21 | (sort-by str ["c" "aa" "a" "b" 1 34 2]) ; (1 2 34 "a" "aa" "b" "c")
22 |
23 | ; with comparable function
24 | (sort-by second > [[:a 2] [:b 7] [:c 3] [:d 6]]) ; ([:b 7] [:d 6] [:c 3] [:a 2])
25 |
26 | (sort-by :age [{:age 99}, {:age 13}, {:age 7}]) ; ({:age 7} {:age 13} {:age 99})
27 |
28 | ; Exercise: sort by the plays/loved ratio
29 | (def plays [{:band "Burial", :plays 979, :loved 9}
30 | {:band "Eno", :plays 2333, :loved 15}
31 | {:band "Bill Evans", :plays 979, :loved 9}
32 | {:band "Magma", :plays 2665, :loved 31}])
33 |
34 | (def sort-by-loved-ratio (partial sort-by #(/ (:plays %) (:loved %))))
35 | (sort-by-loved-ratio plays)
36 | ; ({:band "Magma" :plays 2665 :loved 31}
37 | ; {:band "Burial" :plays 979 :loved 9}
38 | ; {:band "Bill Evans" :plays 979 :loved 9}
39 | ; {:band "Eno" :plays 2333 :loved 15})
40 |
41 | (sort-by (columns [:plays :loved :band]) plays)
42 |
43 |
44 | (map {:band "Bill Evans", :plays 979, :loved 9} [:plays :loved :band])
45 |
46 | ({:band "Bill Evans", :plays 979, :loved 9} :plays)
47 |
--------------------------------------------------------------------------------
/clojure/functions/polymorphism.clj:
--------------------------------------------------------------------------------
1 | (defn poly
2 | ([] (poly "without argument"))
3 | ([arg] (println arg)))
4 |
5 | (poly)
6 | (poly "an arg")
7 |
--------------------------------------------------------------------------------
/clojure/functions/reduce.clj:
--------------------------------------------------------------------------------
1 | ;; Reduce:
2 | ;; - Assemble
3 | ;; - Taking a collection of things and put into one thing as the final product
4 |
5 | ;; Clojure Syntax: (reduce f start coll)
6 | ;; f = function of two arguments
7 | ;; start = initial value
8 | ;; coll = collection
9 |
10 | ;; Some real world examples:
11 | ;; (reduce glue paper noodles)
12 | ;; (reduce paint paper paints)
13 |
14 | ;; (0 1 2 3 4 5 6 7 8 9)
15 | ;; (+ 0 0) --> result: 0
16 | ;; (+ 0 1) --> result: 1
17 | ;; (+ 1 2) --> result: 3
18 | ;; ...
19 | ;; 45
20 | (reduce + 0 (range 0 10))
21 |
22 | ;; (1 2 3 4 5 6 7 8 9)
23 | ;; (+ 1 1) --> result: 1
24 | ;; (+ 1 1) --> result: 1
25 | ;; (+ 1 2) --> result: 2
26 | ;; ...
27 | ;; 362880
28 | (reduce * 1 (range 1 10))
29 |
30 | ;; build a into function
31 | ;; receive a recipient (collection) and a values (another collection)
32 | ;; and returns a new collection with a combination of the two given collection
33 | ;; recipient: (1 2 3)
34 | ;; values: (4 5 6)
35 | ;; (conj (1 2 3) 4) --> (1 2 3 4)
36 | ;; (conj (1 2 3 4) 5) --> (1 2 3 4 5)
37 | ;; (conj (1 2 3 4 5) 6) --> (1 2 3 4 5 6)
38 | (defn new-into
39 | [recipient values]
40 | (reduce conj
41 | recipient values))
42 |
--------------------------------------------------------------------------------
/clojure/functions/returning-functions.clj:
--------------------------------------------------------------------------------
1 | ;; The returned functions are closures,
2 | ;; which means that they can access all the variables that were in scope when the function was created
3 |
4 | (defn inc-maker
5 | "Create a custom incrementor"
6 | [inc-by]
7 | #(+ % inc-by))
8 |
9 | (def inc3 (inc-maker 3))
10 |
11 | (inc3 7) ;; 10
12 |
--------------------------------------------------------------------------------
/elixir/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Elixir
4 |
5 | ## Courses
6 |
7 | - [Elixir School](https://elixirschool.com/en/)
8 | - [PATTERN MATCHING Course](https://thinkingelixir.com/available-courses/pattern-matching/)
9 |
10 |
11 |
--------------------------------------------------------------------------------
/elixir/learn-fp-with-elixir/01.thinking-functional/01.immutable_data.ex:
--------------------------------------------------------------------------------
1 | list = [1, 2, 3, 4]
2 |
3 | list_without_last = List.delete_at(list, -1)
4 | IO.inspect list_without_last # [1, 2, 3]
5 |
6 | list_with_one_more = list ++ [1]
7 | IO.inspect list_with_one_more # [1, 2, 3, 4, 1]
8 |
9 | # the list value is immutable
10 | IO.inspect list # [1, 2, 3, 4]
11 |
--------------------------------------------------------------------------------
/elixir/learn-fp-with-elixir/01.thinking-functional/02.functions.ex:
--------------------------------------------------------------------------------
1 | # simple functions
2 | add2 = fn (n) -> n + 2 end
3 | result = add2.(2)
4 | IO.inspect result
5 |
6 | # passing functions as arguments
7 | animals = ["cat", "dog", "fish"]
8 | uppercase_animals = Enum.map(animals, &String.upcase/1)
9 | IO.inspect uppercase_animals
10 |
11 | # using pipes to process data
12 | def capitalize_words(title) do
13 | title
14 | |> String.split
15 | |> capitalize_all
16 | |> join_with_whitespace
17 | end
18 |
--------------------------------------------------------------------------------
/elixir/learn-fp-with-elixir/02.variables-and-functions/01.values.ex:
--------------------------------------------------------------------------------
1 | # values
2 | "I'm TK" # string
3 | 27 # integer
4 | 10.5 # real number
5 | true # boolean
6 | :ok # atom
7 | {:name, :age} # tuple
8 | [1, 2] # list
9 | %{name: "TK", age: 27} # map
10 | nil # nil
11 |
12 | # value expressions
13 | 37 + 3.7 # 40.7
14 | (2 + 2) * 3 # 12
15 | 2 + 2 * 3 # 8
16 |
17 | # logical expression
18 | true and true # true
19 | true or false # true
20 | true and false # false
21 | false or false # false
22 |
23 | 1 && "I'm TK" # "I'm TK"
24 | "Hello, Word!" && true # true
25 | nil || 1 # 1
26 | 1 || "hi" # 1
27 |
28 | # Anonymous Functions
29 | hello = fn name -> "Hello " <> name <> "!" end
30 | IO.inspect hello.("TK")
31 | IO.inspect hello.("Dan")
32 | IO.inspect hello.("Kaio")
33 |
34 | # using string interpolation
35 | hello = fn name -> "Hello #{name}!" end
36 | IO.inspect hello.("TK")
37 | IO.inspect hello.("Dan")
38 | IO.inspect hello.("Kaio")
39 |
40 | # function without arguments
41 | one_plus_one = fn -> 1 + 1 end
42 | IO.inspect one_plus_one.() # 2
43 |
44 | # functions as value
45 | total_price = fn price, fee -> price * fee.(price) end
46 | flat_fee = fn price -> 5 end
47 | proportional_fee = fn price -> price * 0.12 end
48 |
49 | IO.inspect total_price.(1000, flat_fee) # 1005
50 | IO.inspect total_price.(1000, proportional_fee) # 1120.0
51 |
52 | # working with modules
53 | defmodule Checkout do
54 | def total_cost(price, tax_rate) do
55 | price * (tax_rate + 1)
56 | end
57 | end
58 |
59 | Checkout.total_cost(100, 0.2) # 120.0
60 |
--------------------------------------------------------------------------------
/elixir/learn-fp-with-elixir/02.variables-and-functions/exercises/01.ex:
--------------------------------------------------------------------------------
1 | # Create an expression that solves the following problem:
2 | # Sarah has bought ten slices of bread for ten cents each,
3 | # three bottles of milk for two dollars each, and a cake for fifteen dollars.
4 | # How many dollars has Sarah spent?
5 |
6 | 10 * 0.10 + 3 * 2 + 15 # 22.0
7 |
--------------------------------------------------------------------------------
/elixir/learn-fp-with-elixir/02.variables-and-functions/exercises/02.ex:
--------------------------------------------------------------------------------
1 | # Bob has traveled 200 km in four hours.
2 | # Using variables, print a message showing his travel distance, time, and average velocity.
3 |
4 | distance = 200
5 | time = 4
6 | average_velocity = 200 / 4
7 |
8 | IO.inspect distance
9 | IO.inspect time
10 | IO.inspect average_velocity
11 |
--------------------------------------------------------------------------------
/elixir/learn-fp-with-elixir/02.variables-and-functions/exercises/03.ex:
--------------------------------------------------------------------------------
1 | # Build an anonymous function that applies a tax of 12% to a given price.
2 | # It should print a message with the new price and tax value.
3 | # Bind the anonymous function to a variable called apply_tax.
4 | # You should use apply_tax with Enum.each/2, like in the following example.
5 |
6 | print = fn total_price, taxed_price ->
7 | IO.puts "Price: #{total_price} - Tax: #{taxed_price}"
8 | end
9 |
10 | apply_tax = fn price ->
11 | taxed_price = price * 0.12
12 | total_price = price + taxed_price
13 | print.(total_price, taxed_price)
14 |
15 | total_price
16 | end
17 |
18 | Enum.each [12.5, 30.99, 250.49, 18.80], apply_tax
19 |
--------------------------------------------------------------------------------
/elixir/learn-fp-with-elixir/02.variables-and-functions/exercises/04.ex:
--------------------------------------------------------------------------------
1 | defmodule MatchstickFactory do
2 | def boxes(matchsticks) do
3 | big = div(matchsticks, 50)
4 | remaining_after_big = rem(matchsticks, 50)
5 |
6 | medium = div(remaining_after_big, 20)
7 | remaining_after_medium = rem(remaining_after_big, 20)
8 |
9 | small = div(remaining_after_medium, 5)
10 | remaining_matchsticks = rem(remaining_after_medium, 5)
11 |
12 | %{
13 | big: big,
14 | medium: medium,
15 | small: small,
16 | remaining_matchsticks: remaining_matchsticks
17 | }
18 | end
19 | end
20 |
21 | IO.inspect MatchstickFactory.boxes(98)
22 | IO.inspect MatchstickFactory.boxes(39)
23 |
--------------------------------------------------------------------------------
/elixir/learn-fp-with-elixir/03.using-pattern-matching-to-control-the-program-flow/01.equal_operator.ex:
--------------------------------------------------------------------------------
1 | 1 = 1 # ok
2 | 1 = 2 # raises an error
3 | x = 1 # ok
4 | 1 = x # ok
5 | 2 = x # raises an error
6 |
--------------------------------------------------------------------------------
/elixir/learn-fp-with-elixir/03.using-pattern-matching-to-control-the-program-flow/02.destructuring.ex:
--------------------------------------------------------------------------------
1 | # strings
2 | "Authentication: " <> credentials = "Authentication: Basic dXNlcjpwYXNz"
3 | IO.inspect credentials
4 |
5 | # tuples
6 | {a, b, c} = {1, 2, 3}
7 | IO.inspect a
8 | IO.inspect b
9 | IO.inspect c
10 |
11 | # lists
12 | [a, b, c] = [1, 2, 3]
13 | IO.inspect a
14 | IO.inspect b
15 | IO.inspect c
16 |
17 | [_, x, _] = [1, 2, 3] # this _ operator is called wild card
18 | IO.inspect x
19 |
20 | [head | rest] = [1, 2, 3, 4, 5]
21 | IO.inspect head # 1
22 | IO.inspect rest # [2, 3, 4, 5]
23 |
24 | [first, second | rest] = [1, 2, 3, 4, 5]
25 | IO.inspect first # 1
26 | IO.inspect second # 2
27 | IO.inspect rest # [2, 3, 4, 5]
28 |
29 | [head | rest] = [:a]
30 | IO.inspect head # :a
31 | IO.inspect rest # []
32 |
33 | # maps
34 | user_signup = %{username: "TK", email: "tk@mail.com", password: "123123123"}
35 | IO.inspect user_signup
36 |
37 | user_signup = %{:username => "TK", :email => "tk@mail.com", :password => "123123123"} # another map syntax
38 |
39 | %{email: email} = user_signup
40 | IO.inspect email
41 |
42 | %{username: username = "TK"} = user_signup
43 | IO.inspect username
44 |
--------------------------------------------------------------------------------
/haskell/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Haskell
4 |
5 | ## Table of Content
6 |
7 | - [Videos](#videos)
8 | - [Courses](#courses)
9 | - [Books](#books)
10 |
11 | ## Videos
12 |
13 | - [Haskell 101 @ Google](https://www.youtube.com/watch?v=cTN1Qar4HSw&feature=youtu.be)
14 | - [Haskell 102 @ Google](https://www.youtube.com/watch?v=Ug9yJnOYR4U&feature=youtu.be)
15 |
16 | ## Courses
17 |
18 | - [Functional Programming - edX](https://www.edx.org/course/introduction-to-functional-programming)
19 |
20 | ## Books
21 |
22 | - [The Joy of Haskell](https://joyofhaskell.com/)
23 |
24 |
25 |
--------------------------------------------------------------------------------
/haskell/basics.hs:
--------------------------------------------------------------------------------
1 | head [1, 2, 3, 4, 5] -- get the first: 1
2 | tail [1, 2, 3, 4, 5] -- get the last: 5
3 | take 3 [1, 2, 3, 4, 5] -- get the first n elements: [1, 2, 3]
4 | drop 3 [1, 2, 3, 4, 5] -- remove the first n element: [4, 5]
5 | length [1, 2, 3, 4, 5] -- 5
6 | sum [1, 2, 3, 4, 5] -- sum all elements in the list: 15
7 | product [1, 2, 3, 4, 5] -- product all elements in the list: 120
8 | [1, 2, 3] ++ [4, 5] -- append two lists: [1, 2, 3, 4, 5]
9 | reverse [1, 2, 3, 4, 5] -- reverse all elements in the list: [5, 4, 3, 2, 1]
10 |
--------------------------------------------------------------------------------
/haskell/function_application.hs:
--------------------------------------------------------------------------------
1 | f a + b -- meaning f(a) + b, rather than f(a + b) -- `f` apply to `a`
2 | f a b -- f(a, b)
3 | f (g x) -- f(g(x))
4 | f x (g y) -- f(x, g(y))
5 | f x * g y -- f(x) * g(y)
6 |
--------------------------------------------------------------------------------
/javascript/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # JavaScript Functional Programming
4 |
5 | ## Table of Content
6 |
7 | - [JavaScript](https://github.com/leandrotk/functional-programming-learning-path/tree/master/javascript/javascript/README.md)
8 | - [Beginner](#beginner)
9 | - [Intermediate](#intermediate)
10 | - [Advanced](#advanced)
11 | - [With React](#with-react)
12 | - [Courses](#courses)
13 | - [Books](#books)
14 |
15 | ## Beginner
16 |
17 | - [A repo. that demonstrates use of functional programming in javascript](https://github.com/divyanshu-rawat/Functional-Programming-JS)
18 | - [Entendendo Programação Funcional em JavaScript de uma vez](https://medium.com/tableless/entendendo-programa%C3%A7%C3%A3o-funcional-em-javascript-de-uma-vez-c676489be08b)
19 | - [Two Years of Functional Programming in JavaScript: Lessons Learned](https://hackernoon.com/two-years-of-functional-programming-in-javascript-lessons-learned-1851667c726)
20 | - [Javascript Funcional](https://www.youtube.com/watch?v=k07DBTYj9w8&ab_channel=iMasters)
21 | - [Flavio Corpa's collection of FP's JavaScript functions](https://github.com/kutyel/functional-programming)
22 | - [JavaScript Testing: Unit vs Functional vs Integration Tests](https://www.sitepoint.com/javascript-testing-unit-functional-integration/)
23 | - [Gist: Usages for ES6 destructuring](https://gist.github.com/mikaelbr/9900818)
24 | - [Functional Programming in JavaScript series by mpj](https://www.youtube.com/playlist?list=PL0zVEGEvSaeEd9hlmCXrk5yUyqUag-n84)
25 | - [Pure functions in Javascript](http://nicoespeon.com/en/2015/01/pure-functions-javascript/)
26 | - [Concepts of Functional Programming in Javascript](https://medium.com/the-renaissance-developer/concepts-of-functional-programming-in-javascript-6bc84220d2aa)
27 | - [Functional Programming Basics In ES6](https://www.youtube.com/watch?v=FYXpOjwYzcs&ab_channel=CodingTech)
28 | - [Functional programming with Javascript](https://stephen-young.me.uk/2013/01/20/functional-programming-with-javascript.html)
29 | - [Map, Filter, Reduce in Typescript](https://www.matthewgerstman.com/map-filter-reduce/)
30 |
31 | ## Intermediate
32 |
33 | - [Javascript- Currying VS Partial Application](https://codeburst.io/javascript-currying-vs-partial-application-4db5b2442be8)
34 | - [Variable length currying in JavaScript](https://medium.com/@Charles_Stover/variable-length-currying-in-javascript-7f7bb7bdad8b)
35 |
36 | ## Advanced
37 |
38 | - [Adding pipelines to JavaScript](https://blog.logrocket.com/adding-pipelines-to-javascript-f79ae7311574)
39 | - [Functors by mpj](https://www.youtube.com/watch?v=DisD9ftUyCk)
40 | - [Functors in Javascript](http://functionaljavascript.blogspot.com.br/2013/07/functors.html)
41 | - [JavaScript and Type Thinking](https://medium.com/@yelouafi/javascript-and-type-thinking-735edddc388d)
42 | - [Functional Composition in Javascript](https://joecortopassi.com/articles/functional-composition-in-javascript/)
43 | - [Functors, Applicatives, And Monads In Pictures](http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html)
44 | - [Monads in JavaScript](https://curiosity-driven.org/monads-in-javascript)
45 | - [JavaScript Monads Made Simple](https://medium.com/javascript-scene/javascript-monads-made-simple-7856be57bfe8)
46 |
47 | ## With React
48 |
49 | - [An intro to Functional Programming in JavaScript and React](https://medium.com/@agm1984/an-overview-of-functional-programming-in-javascript-and-react-part-one-10d75b509e9e)
50 | - [Functional Programming in JavaScript and React (Part Two)](https://medium.com/@agm1984/functional-programming-in-javascript-and-react-part-two-521ea9f57d30)
51 | - [Mastering React Functional Components with Recompose](https://hackernoon.com/mastering-react-functional-components-with-recompose-d4dd6ac98834)
52 | - [Taste the principles of functional programming in React](https://codinglawyer.net/index.php/2018/01/31/taste-the-principles-of-functional-programming-in-react/)
53 | - [The functional side of React](https://medium.com/@andrea.chiarelli/the-functional-side-of-react-229bdb26d9a6)
54 | - [Functional React](https://levelup.gitconnected.com/functional-react-is-it-possible-ceaf5ed91bfd)
55 |
56 | ## With Redux
57 |
58 | - [10 Tips for Better Redux Architecture](https://medium.com/javascript-scene/10-tips-for-better-redux-architecture-69250425af44)
59 |
60 | ## Courses
61 |
62 | - [Functional Programming Patterns With RamdaJS!](https://www.educative.io/collection/5070627052453888/5738600293466112)
63 | - [Professor Frisby Introduces Composable Functional JavaScript](https://egghead.io/courses/professor-frisby-introduces-composable-functional-javascript)
64 | - [Introduction to The Beginner's Guide to ReactJS](https://egghead.io/lessons/react-introduction-to-the-beginner-s-guide-to-reactjs)
65 |
66 | ## Books
67 |
68 | - [Professor Frisby's Mostly Adequate Guide to Functional Programming (NEW)](https://mostly-adequate.gitbooks.io/mostly-adequate-guide/content/)
69 | - [Professor Frisby's Mostly Adequate Guide to Functional Programming (OLD)](https://drboolean.gitbooks.io/mostly-adequate-guide/)
70 | - [Functional JavaScript Mini Book by Jichao Ouyang](https://jcouyang.gitbooks.io/functional-javascript/content/en/index.html)
71 | - [Pragmatic Function Javascript online book](https://haskellcamargo.gitbooks.io/pragmatic-functional-javascript/)
72 |
73 | ## Lists
74 |
75 | - [Functional Programming Resources In JavaScript](https://github.com/busypeoples/functional-programming-javascript)
76 | - [Awesome FRP JS](https://github.com/stoeffel/awesome-frp-js)
77 |
78 |
79 |
--------------------------------------------------------------------------------
/javascript/books/composing_software/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Composing Software
4 |
5 | ## Composing Software: An Introduction
6 |
7 | [Source Code - Composing Functions](https://github.com/leandrotk/functional-programming-learning-path/blob/master/javascript/composing_software/composing_functions.js)
8 |
9 |
10 |
--------------------------------------------------------------------------------
/javascript/books/composing_software/composing_functions.js:
--------------------------------------------------------------------------------
1 | const log = input => console.log(input);
2 |
3 | // Function composition is the process of applying a function to the output of another function.
4 | const g = n => n + 1;
5 | const f = n => n * 2;
6 |
7 | const doStuff = x => {
8 | const gOutput = g(x);
9 | const fOutput = f(gOutput);
10 | return fOutput;
11 | };
12 |
13 | let result = doStuff(20);
14 | log(result); // 42
15 |
16 | // A different (better) way to do composition
17 | const doStuffBetter = x => f(g(x));
18 |
19 | result = doStuffBetter(20);
20 | log(result); // 42
21 |
22 | // debugging the doStuff function
23 | const doStuffWithDebugging = x => {
24 | const gOutput = g(x);
25 | console.log(`after g: ${gOutput}`);
26 | const fOutput = f(gOutput);
27 | console.log(`after f: ${fOutput}`);
28 | return fOutput;
29 | };
30 |
31 | doStuffWithDebugging(20);
32 | // after g: 21
33 | // after f: 42
34 |
35 | // debugging the doStuffBetter function
36 | const compose = (...fns) => n => fns.reduceRight((acc, fn) => fn(acc), n);
37 |
38 | const trace = message => input => {
39 | console.log(`${message} ${input}`);
40 | return input;
41 | };
42 |
43 | const doStuffBetterWithDebugging = compose(
44 | trace("after f:"),
45 | f,
46 | trace("after g:"),
47 | g
48 | );
49 |
50 | doStuffBetterWithDebugging(20);
51 | // after g: 21
52 | // after f: 42
53 |
54 | // If you’re chaining, you’re composing.
55 | const list = [1, 2, 3, 4, 5];
56 |
57 | const sumEvenNumbers = list => {
58 | return list
59 | .filter(n => n % 2 == 0)
60 | .map(n => n * 2)
61 | .reduce((previous, current) => previous + current);
62 | };
63 |
64 | log(sumEvenNumbers(list)); // 12
65 |
--------------------------------------------------------------------------------
/javascript/books/composing_software/declarative_programming.js:
--------------------------------------------------------------------------------
1 | // imperative programming: coding every step of the process
2 | const doubleMap = numbers => {
3 | const doubled = [];
4 |
5 | for (let i = 0; i < numbers.length; i++) {
6 | doubled.push(numbers[i] * 2);
7 | }
8 |
9 | return doubled;
10 | };
11 |
12 | doubled.push(numbers[i] * 2);
13 | console.log(doubleMap([2, 3, 4])); // [4,6,8]
14 |
15 | // declarative programming: describing the data flow
16 | const doubleMap = numbers => numbers.map(n => n * 2);
17 | doubleMap([2, 3, 4]); // [4,6,8]
18 |
19 | // Declarative code relies more on expressions. An expression is a piece of code which evaluates to some value.
20 | // Examples of expressions:
21 |
22 | 2 * 2;
23 | doubleMap([2, 3, 4]);
24 | Math.max(4, 3, 2);
25 | "a" + "b" + "c";
26 |
--------------------------------------------------------------------------------
/javascript/books/composing_software/functors.js:
--------------------------------------------------------------------------------
1 | // When you see the word functor, you should think “mappable”.
2 |
3 | const double = n => n * 2;
4 | const doubleMap = numbers => numbers.map(double);
5 | doubleMap([1, 2, 3]); // [2, 4, 6]
6 |
7 | const doublePoints = x => x.points * 2;
8 | const doublePointsMap = numbers => numbers.map(doublePoints);
9 | doublePointsMap([
10 | { name: "ball", points: 2 },
11 | { name: "coin", points: 3 },
12 | { name: "candy", points: 4 }
13 | ]);
14 | // [4, 6, 8]
15 |
--------------------------------------------------------------------------------
/javascript/books/composing_software/intro_to_js.js:
--------------------------------------------------------------------------------
1 | // const instead of let and var most of the time
2 | const number = 1;
3 |
4 | const arr = [1, 2, 3];
5 |
6 | // `const obj = { a: a }` but we have a better way to do it
7 | const a = "a";
8 | const objA = { a };
9 |
10 | const b = "b";
11 | const objB = { b };
12 |
13 | // composing objects with object spread operator
14 | const ab = { ...objA, ...objB }; // { a: 'a', b: 'b' }
15 |
16 | // Destructuring arrays
17 | const [a, b] = ["a", "b"];
18 | a; // 'a'
19 | b; // 'b'
20 |
21 | // destructuring objects
22 | const { one } = { one: 1 };
23 | one; // 1
24 |
25 | // but also do multiple destructuring
26 | const action = { type: "SUM", data: 1 };
27 | const { type, data } = action;
28 |
29 | // we can use this technique in reducers
30 | const reducer = (state = 0, action = {}) => {
31 | const { type, data } = action;
32 |
33 | switch (type) {
34 | case "SUM":
35 | return state + data;
36 | default:
37 | return state;
38 | }
39 | };
40 |
--------------------------------------------------------------------------------
/javascript/books/mostly_adequate_guide_to_functional_programming/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Mostly Adequate Guide to Functional Programming
4 |
5 | ## Chapter 02 - First Class Functions
6 |
7 | [Source Code - First Class Functions](https://github.com/tk-learning-center/functional-programming-learning-path/blob/master/javascript/mostly_adequate_guide_to_functional_programming/ch02.js)
8 |
9 |
10 |
--------------------------------------------------------------------------------
/javascript/books/mostly_adequate_guide_to_functional_programming/ch02.js:
--------------------------------------------------------------------------------
1 | // Chapter 02: First Class Functions
2 |
3 | const hi = name => `Hi ${name}`;
4 |
5 | // const greeting = name => hi(name);
6 | // this is totally redundant,
7 | // because we can treat the greeting function as a value
8 | // and assign this value to the new greeting function, like that:
9 |
10 | const greeting = hi;
11 |
12 | // and use it normal function
13 | greeting('TK'); // Hi TK
14 |
15 | // Another more complex example
16 | // This function `const getServerStuff = callback => ajaxCall(json => callback(json));` is the same as this:
17 | const getServerStuff = ajaxCall;
18 |
19 | // Simplifying this function:
20 | // 1. const getServerStuff = callback => ajaxCall(json => callback(json));
21 | // 2. const getServerStuff = callback => ajaxCall(callback);
22 | // 3 const getServerStuff = ajaxCall;
23 |
24 | // Treating functions as values (first class), it easier to maintain.
25 | // If we have a wrapped function and it needs to change, we need to change both the wrapped function and the call
26 |
27 | // We have this httpGet function
28 | httpGet('/post/2', json => renderPost(json));
29 |
30 | // But we need to change the renderPost function to receive not only the json, but also the error (err)
31 | // We change the renderPost function and the calling
32 | httpGet('/post/2', json, err => renderPost(json, err));
33 |
34 | // Another approach is to treat functions as values and return the renderPost function
35 | // This way we only need to change the renderPost function. The httpGet function stays the same
36 | httpGet('/post/2', renderPost);
37 |
--------------------------------------------------------------------------------
/javascript/books/mostly_adequate_guide_to_functional_programming/ch03.js:
--------------------------------------------------------------------------------
1 | // Chapter 03: Pure Happiness with Pure Functions
2 |
3 | const log = input => console.log(input);
4 |
5 | // impure
6 | let minimum = 21;
7 | const impureCheckAge = age => age >= minimum;
8 |
9 | log(impureCheckAge(21)); // true
10 | minimum = 22;
11 | log(impureCheckAge(21)); // false
12 |
13 | // pure
14 | const checkAge = age => age >= 21;
15 |
16 | log(impureCheckAge(21)); // true
17 | log(impureCheckAge(21)); // true
18 |
--------------------------------------------------------------------------------
/javascript/books/mostly_adequate_guide_to_functional_programming/ch04.js:
--------------------------------------------------------------------------------
1 | // Chapter 04: Currying
2 |
3 | const log = (input) => console.log(input);
4 |
5 | // The add function will return a function expecting the Y parameter,
6 | // but also remembering the X value via closure
7 | const add = x => y => x + y;
8 | const increment = add(1);
9 | const addTen = add(10);
10 |
11 | log(increment(2)); // 3
12 | log(addTen(2)); // 12
13 |
14 | // Curry implementation
15 | const curry = f => {
16 | const fn = (...args) => {
17 | return f.length == args.length ? f(...args) : (...newArgs) => fn(...args, ...newArgs);
18 | }
19 |
20 | return fn;
21 | }
22 |
23 | const f = (x, y, z) => { return x + y + z };
24 |
25 | let curriedAdd = curry(f); // function to curry
26 | let add1 = curriedAdd(1); //curried function with x = 1
27 | let add3 = add1(2); // fn
28 |
29 | log(add3(7)); // 10
30 | log(add1(2, 7)); // 10
31 |
32 | // Exercises
33 | const split = (separator, string) => string.split(separator);
34 | log(split(' ', 'a bunch of words')); // [ 'a', 'bunch', 'of', 'words' ]
35 |
36 | const curriedSplit = curry(split);
37 |
38 | const spaceSplit = curriedSplit(' ');
39 | log(spaceSplit('a bunch of words')); // [ 'a', 'bunch', 'of', 'words' ]
40 |
41 | const hifenSplit = curriedSplit('-');
42 | log(hifenSplit('a-bunch-of-words')); // [ 'a', 'bunch', 'of', 'words' ]
43 |
--------------------------------------------------------------------------------
/javascript/closure.js:
--------------------------------------------------------------------------------
1 | const log = (...args) => console.log(...args);
2 |
3 | const posts = [
4 | { id: '0001', title: 'Title 0001' },
5 | { id: '0002', title: 'Title 0002' },
6 | { id: '0003', title: 'Title 0003' },
7 | { id: '0004', title: 'Title 0004' }
8 | ]
9 |
10 | const findIn = (list = []) => ({
11 | where: (field) => ({
12 | isEqualTo: (value) => {
13 | return list.find(el => el[field] === value);
14 | }
15 | })
16 | });
17 |
18 | // the field is fixed in the isEqualTo function scope
19 | // so it has access to the value
20 |
21 | log(
22 | findIn(posts)
23 | .where('id')
24 | .isEqualTo('0001')
25 | );
26 |
--------------------------------------------------------------------------------
/javascript/currying.js:
--------------------------------------------------------------------------------
1 | const log = (...args) => console.log(...args);
2 |
3 | const add = (x) => (y) => x + y;
4 |
5 | /***
6 | const add = (x) => {
7 | return (y) => {
8 | Fix x = ?
9 | x + y;
10 | }
11 | }
12 | ***/
13 |
14 | const increment = add(1);
15 |
16 | let one = 1;
17 | let two = increment(one);
18 | let three = increment(two);
19 |
20 | log(two); // 2
21 | log(three); // 3
22 |
23 | const addTen = add(10);
24 |
25 | log(addTen(10)); // 20
26 | log(addTen(0)); // 10
27 |
28 | // ---------------------------------------------------------------------------------------------
29 |
30 | // Outside of function composition, currying is a useful abstraction we can use to specialize functions
31 | // One example is to curry the map function
32 |
33 | const map = fn => mappable => mappable.map(fn);
34 |
35 | const arr = [1, 2, 3, 4, 5];
36 | const isEven = n => n % 2 === 0;
37 |
38 | const stripe = n => isEven(n) ? 'dark' : 'light';
39 | const stripeAll = map(stripe);
40 | const striped = stripeAll(arr);
41 | log(striped); // => ['light', 'dark', 'light', 'dark', 'light']
42 |
43 | const double = n => n * 2;
44 | const doubleAll = map(double);
45 | const doubled = doubleAll(arr);
46 | log(doubled); // => [2, 4, 6, 8, 10]
47 |
48 | // Get element by value from list of objects
49 | // Using currying for specialized functions
50 |
51 | const posts = [
52 | { id: '0001', title: 'Title 0001' },
53 | { id: '0002', title: 'Title 0002' },
54 | { id: '0003', title: 'Title 0003' },
55 | { id: '0004', title: 'Title 0004' }
56 | ]
57 |
58 | const getFromBasic = (list, field) => (value) =>
59 | list[list.map(el => el[field]).indexOf(value)];
60 |
61 | const getByIdBasic = (list, field = "id") => getFromBasic(list, field);
62 |
63 | let selected = getByIdBasic(posts)('0003');
64 | log(selected);
65 |
66 | const getFrom = (field) => (list) => (value) =>
67 | list[list.map(el => el[field]).indexOf(value)];
68 |
69 | const getById = getFrom('id');
70 | const getByTitle = getFrom('title');
71 |
72 | selected = getById(posts)('0003');
73 | log(selected);
74 | selected = getByTitle(posts)('Title 0004');
75 | log(selected);
76 |
77 | // ---------------------------------------------------------------------------------------------
78 |
79 | /*
80 | jQuery approach
81 | $('some-css-class').on('click', callback);
82 | */
83 |
84 | /*
85 | How I want to use
86 | - onClick(element, handler);
87 | - onHover(element, handler);
88 | */
89 |
90 | /*
91 | A more generic approach
92 | (event) => (element, handler) => fn
93 |
94 | The idea is to use curry
95 | - receive the event string first and return a new function
96 | - the new function receives the element and the callback handler
97 | - passing the event string first helps to create specialized functions (e.g. onClick and onHover)
98 | */
99 | const eventListener = (event) => (element, handler) => element.addEventListener(event, handler);
100 |
101 | const onClick = eventListener('click');
102 | const onHover = eventListener('hover');
103 |
104 | /*
105 | Example: on click event for the vote button
106 | This example runs page this StackOverflow page
107 | https://stackoverflow.com/questions/6348494/addeventlistener-vs-onclick
108 | */
109 | const voteUpButton = document.getElementsByClassName('js-vote-up-btn')[0];
110 | const helloAlert = () => alert('Hello!');
111 |
112 | onClick(voteUpButton, helloAlert);
113 |
--------------------------------------------------------------------------------
/javascript/first_class_citizens.js:
--------------------------------------------------------------------------------
1 | /*
2 | Functions as first class citizens: Treats functions as values
3 | - Refer to it from constants and variables
4 | - Pass it as a parameter to other functions
5 | - Return it as result from other functions
6 | */
7 |
--------------------------------------------------------------------------------
/javascript/function_as_value.js:
--------------------------------------------------------------------------------
1 | const sum = (a, b) => a + b;
2 | const subtraction = (a, b) => a - b;
3 |
4 | const doubleSum = (a, b) => sum(a, b) * 2;
5 | const doubleSubtraction = (a, b) => subtraction(a, b) * 2;
6 |
7 | const doubleOperator = (f, a, b) => f(a, b) * 2;
8 |
9 | doubleOperator(sum, 1, 1);
10 | doubleOperator(subtraction, 3, 1);
11 |
12 | const doubleOperator = (f) => (a, b) => f(a, b) * 2;
13 |
14 | const doubleSum = doubleOperator(sum);
15 | const doubleSubtraction = doubleOperator(subtraction);
16 |
17 | doubleSum(1, 1);
18 | doubleSubtraction(3, 1);
--------------------------------------------------------------------------------
/javascript/function_composition.js:
--------------------------------------------------------------------------------
1 | const log = (...args) => console.log(...args);
2 |
3 | /*
4 | Function Composition combines two or more functions together
5 | To perform function composition,
6 | you simply have the result of each function be passed as the argument to the next
7 |
8 | As an example we'll implement a simple function that calculates total purchase price
9 | by taking the purchase price, applying an 8% tax, and adding $10 (shipping and handling)
10 | */
11 |
12 | const calculateTotalBasic = (amount) => {
13 | return (amount * 1.08) + 10;
14 | }
15 |
16 | /*
17 | Now let's refactor it:
18 | - implement applyTax function
19 | - implement applyShippingAndHandling
20 | - compose those functions into the calculate function
21 | */
22 |
23 | const applyTax = (amount) => amount * 1.08;
24 |
25 | const applyShippingAndHandling = (amount) => amount + 10;
26 |
27 | const calculateTotal = (amount) => {
28 | return applyShippingAndHandling(applyTax(amount));
29 | }
30 |
31 | // compose function using reduce
32 | const compose = (...fns) => (x) => {
33 | return fns.reduceRight((composedFns, fn) => fn(composedFns), x)
34 | };
35 |
36 | const shoutBasic = (str) => `${str.toUpperCase()}!`;
37 |
38 | log(shoutBasic('something'));
39 | log(shoutBasic('something else'));
40 | log(shoutBasic('nothing'));
41 |
42 | // compose toUpperCase and exclaim functions
43 | const toUpperCase = (str) => str.toUpperCase();
44 | const exclaim = (str) => `${str}!`;
45 | const shout = compose(exclaim, toUpperCase);
46 |
47 | log(shout('something'));
48 | log(shout('something else'));
49 | log(shout('nothing'));
50 |
--------------------------------------------------------------------------------
/javascript/high_order_functions.js:
--------------------------------------------------------------------------------
1 | /*
2 | Higher-order functions are functions that work on other functions
3 | Meaning that they can take one or more functions as an argument and
4 | can also return a function as a result
5 | */
6 |
7 | /*
8 | Imagine you have this element in the HTML:
9 |
10 |
11 | Let's add a click event listener to the button
12 | */
13 |
14 | document.getElementById("btn").addEventListener("click", () => {
15 | console.log("You clicked me!");
16 | });
17 |
18 | /* We can also extract the logger code in a function to be explicit */
19 |
20 | const logger = (message) => () => { console.log(message); };
21 | const clickLogger = logger('You clicked me');
22 |
23 | document.getElementById('btn').addEventListener('click', clickLogger);
24 |
25 | /* addEventListener is a high order function */
26 |
--------------------------------------------------------------------------------
/javascript/immutability/avoid_array_mutability.js:
--------------------------------------------------------------------------------
1 | // fill
2 | var ar = [1, 2, 3, 4]
3 | ar.fill(0, 2, 4) // (4) [1, 2, 0, 0]
4 | ar // (4) [1, 2, 0, 0]
5 |
6 | // pop
7 | var ar = [1, 2, 3, 4]
8 | ar.pop() // 4
9 | ar // (3) [1, 2, 3]
10 |
11 | // push
12 | var ar = [1, 2, 3, 4]
13 | ar.push(5) // 5
14 | ar // (5) [1, 2, 3, 4, 5]
15 |
16 | // reverse
17 | var ar = [1, 2, 3, 4]
18 | ar.reverse() // (4) [4, 3, 2, 1]
19 | ar // (4) [4, 3, 2, 1]
20 |
21 | // shift
22 | var ar = [1, 2, 3, 4]
23 | ar.shift() // 1
24 | ar // (3) [2, 3, 4]
25 |
26 | // sort
27 | var ar = [1, 4, 3, 2]
28 | ar.sort() // (4) [1, 2, 3, 4]
29 | ar // (4) [1, 2, 3, 4]
30 |
31 | // splice
32 | var ar = [1, 2, 3, 5]
33 | ar.splice(3, 0, 4) // []
34 | ar // (5) [1, 2, 3, 4, 5]
35 |
36 | // unshift
37 | var ar = [3, 4]
38 | ar.unshift(1, 2) // 4
39 | ar // (4) [1, 2, 3, 4]
40 |
--------------------------------------------------------------------------------
/javascript/immutability/immutability.js:
--------------------------------------------------------------------------------
1 | /* Strings are immutable */
2 | var name = 'TK';
3 | name[0] = 'D';
4 | console.log(name); // 'TK'
5 |
6 | /*
7 | immutable data is important because we need to be able to attach dependable, unchanging values to our functions
8 |
9 | In multi-threaded applications that is a great thing.
10 | It allows for a thread to act on data represented by immutable objects
11 | without worrying what other threads are up to.
12 |
13 | immutable objects are more thread-safe than mutable objects.
14 | */
15 |
16 | // When creating a "constant", we can't reference another value to it.
17 | const reference = 1;
18 | // reference = 2; => TypeError: Assignment to constant variable.
19 |
20 | // We can create another array by using array destructuring
21 | const array = [1, 2];
22 |
23 | const newArray = [...array, 3];
24 |
25 | console.log(newArray);
26 |
27 | // We can create another object by using object destructuring
28 | const object = {
29 | one: 1,
30 | two: 2
31 | };
32 |
33 | const newObject = { ...object, three: 3 };
34 |
35 | console.log(newObject);
36 |
--------------------------------------------------------------------------------
/javascript/immutability/slugify.js:
--------------------------------------------------------------------------------
1 | const urlWithMutation = ' I will be a url slug ';
2 |
3 | const slugifyWithMutation = (url) => {
4 | url = url.toLowerCase();
5 | url = url.trim();
6 | url = url.split(' ');
7 | url = url.join('-');
8 | return url;
9 | }
10 |
11 | slugifyWithMutation(urlWithMutation); // i-will-be-a-url-slug
12 |
13 | const url = ' I will be a url slug ';
14 |
15 | const slugify = (url) =>
16 | url
17 | .toLowerCase()
18 | .trim()
19 | .split(' ')
20 | .join('-');
21 |
22 | slugify(url); // i-will-be-a-url-slug
23 |
--------------------------------------------------------------------------------
/javascript/lazy.js:
--------------------------------------------------------------------------------
1 | const sum = (a, b) => a + b;
2 |
3 | const result = sum(1 + 2, 3);
4 | console.log(result);
5 |
6 | const lazySum = (a, b) => () => a() + b();
7 |
8 | const lazyResult = lazySum(() => 1 + 2, () => 3)();
9 | console.log(lazyResult);
10 |
--------------------------------------------------------------------------------
/javascript/partial_application.js:
--------------------------------------------------------------------------------
1 | /*
2 | Partial application is a way to turn a function that expects multiple parameters
3 | into one that will keep returning a new function until it receives all its arguments
4 |
5 | "partially apply" some of the arguments now, filling in the rest later.
6 |
7 | Partial application allows us to partially apply certain argument to create
8 | new functions out of existing ones.
9 | */
10 |
11 | const calculateTotal = (amount) => {
12 | return (amount * 1.08) + 10;
13 | }
14 |
15 | const R = require('ramda');
16 | const applyTaxOfEightPercent = R.partial(applyTax, [0.08]);
17 |
18 | applyTaxOfEightPercent(100); // 108
19 | applyTaxOfEightPercent(200); // 216
20 | applyTaxOfEightPercent(190); // 205.2
21 | applyTaxOfEightPercent(10000); // 10800
22 |
--------------------------------------------------------------------------------
/javascript/purity_part_1.js:
--------------------------------------------------------------------------------
1 | /*
2 | There are two qualities that make a function "pure":
3 | - The function depends only on the input provided to it to produce a result (and not on any external state).
4 | - The function does not cause any observable side effects, such as modifying a global object or modifying a parameter passed by reference.
5 | */
6 |
7 | const PI = 3.14;
8 |
9 | /* Not pure: it uses the global constant */
10 | const calculateArea = (radius) => radius * radius * PI;
11 |
12 | /* Pure: it uses only parameters passed to the function */
13 | const calculateArea = (radius, PI) => radius * radius * PI;
14 |
15 | /* ------------------------------------------------------ */
16 |
17 | let count = 1;
18 |
19 | /* Not pure: it uses the global variable and modify the variable */
20 | const increaseCount = (value) => count = count + value;
21 |
22 | /* ------------------------------------------------------ */
23 |
24 | /* Not pure: it modifies the array - the reverse method reverses the array in place */
25 | const reverseArray = (array) => array.reverse();
26 |
27 | /* ------------------------------------------------------ */
28 |
29 | /* Not pure: make call to an external API */
30 | async function amountExceedsBuyLimit(amount) {
31 | const limit = await getBuyLimits(); /* assume API call */
32 | return amount > limit;
33 | }
34 |
35 | /* Pure */
36 | async function amountExceedsBuyLimit(amount, limit) {
37 | return amount > limit;
38 | }
39 |
--------------------------------------------------------------------------------
/javascript/purity_part_2.js:
--------------------------------------------------------------------------------
1 | /* Benefit 1: Pure functions are predictable */
2 |
3 | const PI = 3.14;
4 | const calculateArea = (radius) => radius * radius * PI;
5 |
6 | /*
7 | This impure function is reliant on the global variable PI to make the calculation
8 | The PI is a global variable, so anyone can update it, and automatically change the result of calculateArea function
9 | Inpure functions are unpredictable
10 | */
11 |
12 | /* ------------------------------------------------------ */
13 |
14 | /* Benefit 2: Pure functions are easy to test */
15 |
16 | /* Imagine test this impure function */
17 | async function amountExceedsBuyLimit(amount) {
18 | const limit = await getBuyLimits(); /* assume API call */
19 | return amount > limit;
20 | }
21 |
22 | /* We need to mock the API call to test our function */
23 | describe('amountExceedsBuyLimit', () => {
24 | let scope, limits;
25 |
26 | /* Mock API call */
27 | before(() => {
28 | scope = nock('https://myApi.com');
29 | scope
30 | .get('/buyLimit')
31 | .matchHeader('Content-Type', 'application/json')
32 | .reply(200, {
33 | buyLimit: 5000,
34 | });
35 | });
36 |
37 | /* Test the function */
38 | it('is false', () => {
39 | const amountExceedsLimit = amountExceedsBuyLimit(200);
40 | expect(amountExceedsLimit).to.be.false();
41 | });
42 |
43 | it('is true', () => {
44 | const amountExceedsLimit = amountExceedsBuyLimit(10000);
45 | expect(amountExceedsLimit).to.be.true();
46 | });
47 | });
48 |
49 | /* Now imagine test this pure function */
50 | async function amountExceedsBuyLimit(amount, limit) {
51 | return amount > limit;
52 | }
53 |
54 | /* Pretty simple */
55 | describe('amountExceedsBuyLimit', () => {
56 | it('is false', () => {
57 | const amountExceedsLimit = amountExceedsBuyLimit(200, 5000);
58 | expect(amountExceedsLimit).to.be.false();
59 | });
60 |
61 | it('is true', () => {
62 | const amountExceedsLimit = amountExceedsBuyLimit(10000, 5000);
63 | expect(amountExceedsLimit).to.be.true();
64 | });
65 | });
66 |
--------------------------------------------------------------------------------
/javascript/reduce.js:
--------------------------------------------------------------------------------
1 | const log = (...args) => console.log(...args);
2 |
3 | const arr = [1, 2, 3, 4, 5];
4 |
5 | // Building a sum function with reduce
6 | const sumReducer = (acc, value) => acc + value;
7 |
8 | log('Sum with Reduce');
9 | let total = arr.reduce(sumReducer, 0);
10 | log(total); // 15
11 | log();
12 |
13 | /* -------------------------------------- */
14 |
15 | // Building map function with reduce
16 | // API: map(fn, arr);
17 | // fn => function that will process each element in the collection
18 | // arr => the collection to be processed
19 | // [1, 2, 3, 4, 5] => fn => [2, 4, 6, 8, 10]
20 |
21 | const map = (fn, arr) => arr.reduce((acc, value) => {
22 | return acc.concat(fn(value));
23 | }, []);
24 |
25 | const timesTwo = value => value * 2;
26 | const increment = value => value + 1;
27 | const isEven = value => value % 2 === 0;
28 |
29 | let timesTwoMapping = map(timesTwo, arr);
30 | let incrementMapping = map(increment, arr);
31 | let isEvenMapping = map(isEven, arr);
32 |
33 | log('Map with Reduce');
34 | log(timesTwoMapping); // [2, 4, 6, 8, 10]
35 | log(incrementMapping); // [2, 3, 4, 5, 6]
36 | log(isEvenMapping); // [false, true, false, true, false]
37 | log();
38 |
39 | /* -------------------------------------- */
40 |
41 | // Building a filter function with reduce
42 | // API: filter(fn, arr);
43 | // fn => function that will be used to filter each element of the collection
44 | // arr => the collection to be processed
45 |
46 | const filter = (fn, arr) => arr.reduce((acc, value) => {
47 | return fn(value) ? acc.concat(value) : acc
48 | }, []);
49 |
50 | const moreThan3 = value => value > 3;
51 |
52 | let moreThan3Value = filter(moreThan3, arr);
53 | let evenValues = filter(isEven, arr);
54 |
55 | log('Filter with Reduce');
56 | log(moreThan3Value); // [4, 5]
57 | log(evenValues); // [2, 4]
58 | log();
59 |
60 | /* -------------------------------------- */
61 |
62 | // Building a compose function with reduce
63 | // API: compose(fn1, fn2, fn3, ...)
64 | // fn1: function to be composed
65 |
66 | const compose = (...fns) => x => {
67 | return fns.reduceRight((composedFns, fn) => fn(composedFns), x)
68 | };
69 |
70 | const f = (x) => x + 1;
71 | const g = (x) => x / 2;
72 | const h = (x) => x * 3;
73 |
74 | const composedFns = compose(f, g, h);
75 | let finalValue = composedFns(2);
76 |
77 | log('Compose with Reduce');
78 | log(finalValue); // 4
79 | log();
80 |
81 | /* -------------------------------------- */
82 |
83 | // Building a pipe function with reduce
84 | // API: pipe(fn1, fn2, fn3, ...)
85 | // fn1: function to be composed
86 |
87 | const pipe = (...fns) => x => fns.reduce((pipedFns, fn) => fn(pipedFns), x);
88 |
89 | const pipedFns = pipe(f, g, h);
90 | finalValue = pipedFns(1);
91 |
92 | log('Pipe with Reduce');
93 | log(finalValue); // 3
94 | log();
95 |
--------------------------------------------------------------------------------
/javascript/referentially_transparent_function.js:
--------------------------------------------------------------------------------
1 | /*
2 | If a function consistently yields the same result for the same input,
3 | it is referentially transparent.
4 | */
5 |
6 | const square = (x) => x * x;
7 |
8 | console.log(square(4)) /* 16 */
9 | console.log(square(4)) /* 16 */
10 | console.log(square(4)) /* 16 */
11 | console.log(square(4)) /* 16 */
12 |
13 | /*
14 | “well, doesn't every function return the same result for the same input?”.
15 | Consider this function that handle a random number
16 | */
17 |
18 | const getRandomNumber = (max, min) => Math.random() * (max - min) + min;
19 |
20 | getRandomNumber(10, 2)
21 | getRandomNumber(10, 2)
22 | getRandomNumber(10, 2)
23 |
24 | /*
25 | referential transparency gives us the ability to freely replace an expression
26 | with its value and not change the behavior of the program.
27 |
28 | f(4) can be replaced with 16,
29 | g(4) can be replaced with 20,
30 | and the result is not changed.
31 |
32 | f(x) = x * x
33 | f(4) = 16
34 |
35 | g(x) = f(x) + x
36 | g(4) = f(4) + 4
37 | g(4) = 16 + 4
38 | g(4) = 20
39 |
40 | Pure functions + immutable data = referential transparency
41 |
42 | Some benefits:
43 | It makes it much easier to refactor and rewrite programs.
44 | - Since a pure, referentially transparent function can be freely replaced by it’s value,
45 | the only thing we have to worry about when we refactor it is that we get the same
46 | value for a given input.
47 |
48 | - The function doesn’t have any side effects or external dependencies.
49 | This lets us focus on refactoring the single function without having
50 | to worry about all the baggage associated with the function in the outside world.
51 | */
52 |
--------------------------------------------------------------------------------
/programming_challenges/4clojure/problem01.clj:
--------------------------------------------------------------------------------
1 | ; http://www.4clojure.com/problem/1
2 | (= true true)
3 |
--------------------------------------------------------------------------------
/programming_challenges/4clojure/problem02.clj:
--------------------------------------------------------------------------------
1 | ; http://www.4clojure.com/problem/2
2 | (= (- 10 (* 2 3)) 4)
3 |
--------------------------------------------------------------------------------
/programming_challenges/4clojure/problem03.clj:
--------------------------------------------------------------------------------
1 | ; http://www.4clojure.com/problem/3#prob-title
2 | (= "HELLO WORLD" (.toUpperCase "hello world"))
3 |
--------------------------------------------------------------------------------
/programming_challenges/4clojure/problem04.clj:
--------------------------------------------------------------------------------
1 | ;; http://www.4clojure.com/problem/4
2 |
3 | (= (list :a :b :c) '(:a :b :c))
4 |
--------------------------------------------------------------------------------
/programming_challenges/4clojure/problem05.clj:
--------------------------------------------------------------------------------
1 | ;; http://www.4clojure.com/problem/5#prob-title
2 |
3 | (= '(1 2 3 4) (conj '(2 3 4) 1))
4 | (= '(1 2 3 4) (conj '(3 4) 2 1))
5 |
--------------------------------------------------------------------------------
/programming_challenges/4clojure/problem06.clj:
--------------------------------------------------------------------------------
1 | ;; http://www.4clojure.com/problem/6
2 |
3 | (= [:a :b :c] (list :a :b :c) (vec '(:a :b :c)) (vector :a :b :c))
4 |
--------------------------------------------------------------------------------
/programming_challenges/4clojure/problem07.clj:
--------------------------------------------------------------------------------
1 | ;; http://www.4clojure.com/problem/7
2 |
3 | (= [1 2 3 4] (conj [1 2 3] 4))
4 | (= [1 2 3 4] (conj [1 2] 3 4))
5 |
--------------------------------------------------------------------------------
/programming_challenges/4clojure/problem19.clj:
--------------------------------------------------------------------------------
1 | ; http://www.4clojure.com/problem/19
2 |
3 | ; Solution 1
4 | (fn [coll]
5 | (loop [item (first coll)
6 | coll coll]
7 | (if (empty? (rest coll))
8 | item
9 | (recur (first (rest coll)) (rest coll)))))
10 |
11 | ; Solution 2
12 | (fn [coll]
13 | (first (reverse coll)))
14 |
15 | ; Solution 3
16 | #(first (reverse %))
17 |
18 | ; Solution 4
19 | (comp first reverse)
20 |
21 | ; Solution 5
22 | (fn [coll]
23 | (-> coll
24 | reverse
25 | first))
26 |
27 | ; Solution 6
28 | (fn [coll]
29 | (loop [[item & remaining] coll]
30 | (if (empty? remaining)
31 | item
32 | (recur remaining))))
33 |
--------------------------------------------------------------------------------
/programming_challenges/4clojure/problem20.clj:
--------------------------------------------------------------------------------
1 | ; http://www.4clojure.com/problem/20
2 |
3 | (comp second reverse)
4 |
--------------------------------------------------------------------------------
/programming_challenges/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Resources
4 |
5 | ## Websites
6 |
7 | - [4Clojure](http://www.4clojure.com/)
8 | - [Clojure Koans](https://github.com/functional-koans/clojure-koans)
9 | - [Exercism Clojure Track](https://exercism.io/my/tracks/clojure)
10 | - [Exercism JavaScript Track](https://exercism.io/my/tracks/javascript)
11 | - [Hacker Rank FP Path](https://www.hackerrank.com/domains/fp)
12 | - [Clojure Katas](https://github.com/marshallshen/clojure-katas)
13 | - [Wonderland Clojure Katas](https://github.com/gigasquid/wonderland-clojure-katas)
14 |
15 | ## Blogs
16 |
17 | - [Acing Nubank’s technical exercise — part 1](https://medium.com/building-nubank/acing-nubanks-technical-exercise-part-1-59c8a6d3829d)
18 | - [Acing Nubank’s technical exercise — part 2](https://medium.com/building-nubank/acing-nubanks-technical-exercise-part-2-2366c933977e)
19 |
20 |
21 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/armstrong-numbers/.lein-failures:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/armstrong-numbers/.lein-repl-history:
--------------------------------------------------------------------------------
1 | (defn int->digits [int]
2 | (map (comp #(- % 48) int) (str int)))
3 | (defn power-by-two [digits]
4 | (map #(* % (count digits)) digits))
5 | (defn powered-sum [num]
6 | (->> num
7 | int->digits
8 | power-by-two
9 | (reduce +)))
10 | (defn armstrong? [num]
11 | (= (powered-sum num) num))
12 | (armstrong? 123)
13 | (int->digits 123)
14 | quit
15 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/armstrong-numbers/README.md:
--------------------------------------------------------------------------------
1 | # Armstrong Numbers
2 |
3 | An [Armstrong number](https://en.wikipedia.org/wiki/Narcissistic_number) is a number that is the sum of its own digits each raised to the power of the number of digits.
4 |
5 | For example:
6 |
7 | - 9 is an Armstrong number, because `9 = 9^1 = 9`
8 | - 10 is *not* an Armstrong number, because `10 != 1^2 + 0^2 = 1`
9 | - 153 is an Armstrong number, because: `153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153`
10 | - 154 is *not* an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190`
11 |
12 | Write some code to determine whether a number is an Armstrong number.
13 | ## Source
14 |
15 | Wikipedia [https://en.wikipedia.org/wiki/Narcissistic_number](https://en.wikipedia.org/wiki/Narcissistic_number)
16 |
17 | ## Submitting Incomplete Solutions
18 | It's possible to submit an incomplete solution so you can see how others have completed the exercise.
19 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/armstrong-numbers/project.clj:
--------------------------------------------------------------------------------
1 | (defproject armstrong-numbers "0.1.0-SNAPSHOT"
2 | :description "armstrong-numbers exercise"
3 | :url "https://github.com/exercism/clojure/tree/master/exercises/armstrong-numbers"
4 | :dependencies [[org.clojure/clojure "1.10.0"]])
5 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/armstrong-numbers/src/armstrong_numbers.clj:
--------------------------------------------------------------------------------
1 | (ns armstrong-numbers)
2 |
3 | (defn int->digits [num]
4 | (map (comp #(- % 48) int) (str num)))
5 |
6 | (defn power-by-two [digits digit]
7 | (reduce * (repeat (count digits) digit)))
8 |
9 | (defn power-all-by-two [digits]
10 | (map (partial power-by-two digits) digits))
11 |
12 | (defn powered-sum [num]
13 | (->> num
14 | int->digits
15 | power-all-by-two
16 | (reduce +)))
17 |
18 | (defn armstrong? [num]
19 | (= (powered-sum num) num))
20 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/armstrong-numbers/target/classes/META-INF/maven/armstrong-numbers/armstrong-numbers/pom.properties:
--------------------------------------------------------------------------------
1 | #Leiningen
2 | #Thu Jan 31 22:57:53 BRST 2019
3 | groupId=armstrong-numbers
4 | artifactId=armstrong-numbers
5 | version=0.1.0-SNAPSHOT
6 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/armstrong-numbers/target/stale/leiningen.core.classpath.extract-native-dependencies:
--------------------------------------------------------------------------------
1 | [{:dependencies {org.clojure/clojure {:vsn "1.10.0", :native-prefix nil}, org.clojure/spec.alpha {:vsn "0.2.176", :native-prefix nil}, org.clojure/core.specs.alpha {:vsn "0.2.44", :native-prefix nil}, nrepl {:vsn "0.5.3", :native-prefix nil}, nrepl/bencode {:vsn "1.0.0", :native-prefix nil}, clojure-complete {:vsn "0.2.5", :native-prefix nil}}, :native-path "target/native"} {:native-path "target/native", :dependencies {org.clojure/clojure {:vsn "1.10.0", :native-prefix nil, :native? false}, org.clojure/spec.alpha {:vsn "0.2.176", :native-prefix nil, :native? false}, org.clojure/core.specs.alpha {:vsn "0.2.44", :native-prefix nil, :native? false}, nrepl {:vsn "0.5.3", :native-prefix nil, :native? false}, nrepl/bencode {:vsn "1.0.0", :native-prefix nil, :native? false}, clojure-complete {:vsn "0.2.5", :native-prefix nil, :native? false}}}]
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/armstrong-numbers/test/armstrong_numbers_test.clj:
--------------------------------------------------------------------------------
1 | (ns armstrong-numbers-test
2 | (:require [clojure.test :refer [deftest is testing]]
3 | [armstrong-numbers :refer [armstrong?]]))
4 |
5 | (deftest armstrong-number-5
6 | (testing "Single digit numbers are Armstrong numbers"
7 | (is (armstrong? 5))))
8 |
9 | (deftest not-armstrong-number-10
10 | (testing "There are no 2 digit Armstrong numbers"
11 | (is (not (armstrong? 10)))))
12 |
13 | (deftest armstrong-number-153
14 | (testing "Three digit number that is an Armstrong number"
15 | (is (armstrong? 153))))
16 |
17 | (deftest not-armstrong-number-100
18 | (testing "Three digit number that is not an Armstrong number"
19 | (is (not (armstrong? 100)))))
20 |
21 | (deftest armstrong-number-9474
22 | (testing "Four digit number that is an Armstrong number"
23 | (is (armstrong? 9474))))
24 |
25 | (deftest not-armstrong-number-9475
26 | (testing "Four digit number that is not an Armstrong number"
27 | (is (not (armstrong? 9476)))))
28 |
29 | (deftest armstrong-number-9926315
30 | (testing "Seven digit number that is an Armstrong number"
31 | (is (armstrong? 9926315))))
32 |
33 | (deftest not-armstrong-number-9926314
34 | (testing "Seven digit number that is not an Armstrong number"
35 | (is (not (armstrong? 9926314)))))
36 |
37 | (deftest armstrong-number-21897142587612075
38 | (testing "Seventeen digit number that is an Armstrong number"
39 | (is (armstrong? 21897142587612075))))
40 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/hello-world/README.md:
--------------------------------------------------------------------------------
1 | # Hello World
2 |
3 | The classical introductory exercise. Just say "Hello, World!".
4 |
5 | ["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is
6 | the traditional first program for beginning programming in a new language
7 | or environment.
8 |
9 | The objectives are simple:
10 |
11 | - Write a function that returns the string "Hello, World!".
12 | - Run the test suite and make sure that it succeeds.
13 | - Submit your solution and check it at the website.
14 |
15 | If everything goes well, you will be ready to fetch your first real exercise.
16 |
17 | ### Project Structure
18 |
19 | Clojure exercises in exercism use [leiningen](http://leiningen.org/) to configure and run your code
20 | and use [leiningen standard directory structure](https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#directory-layout).
21 |
22 | You will find a test file named `hello_world_test.clj` inside `test` directory.
23 | Write your code in `src/hello_world.clj`. It should use the namespace `hello-world` so that tests can pick it up.
24 |
25 | ### Running tests
26 |
27 | Run the tests using `lein test` command and make them pass:
28 |
29 | ```
30 | $ lein test
31 |
32 | lein test hello-world-test
33 |
34 | Ran 1 tests containing 1 assertions.
35 | 0 failures, 0 errors.
36 | ```
37 |
38 | Then submit the exercise using:
39 |
40 | ```
41 | $ exercism submit src/hello_world.clj
42 | ```
43 |
44 | For more detailed instructions and learning resources refer [exercism's clojure language page](http://exercism.io/languages/clojure).
45 |
46 | ## Source
47 |
48 | This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
49 |
50 | ## Submitting Incomplete Solutions
51 | It's possible to submit an incomplete solution so you can see how others have completed the exercise.
52 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/hello-world/project.clj:
--------------------------------------------------------------------------------
1 | (defproject hello-world "0.1.0-SNAPSHOT"
2 | :description "hello-world exercise."
3 | :url "https://github.com/exercism/clojure/tree/master/exercises/hello-world"
4 | :dependencies [[org.clojure/clojure "1.9.0"]])
5 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/hello-world/src/hello-world.clj:
--------------------------------------------------------------------------------
1 | (ns hello-world)
2 |
3 | (defn hello [] "Hello, World!")
4 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/hello-world/test/hello-world-test.clj:
--------------------------------------------------------------------------------
1 | (ns hello-world-test
2 | (:require [clojure.test :refer [deftest is]]
3 | hello-world))
4 |
5 | (deftest hello-world-test
6 | (is (= "Hello, World!" (hello-world/hello))))
7 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/two-fer/.lein-failures:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/two-fer/.nrepl-port:
--------------------------------------------------------------------------------
1 | 62204
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/two-fer/README.md:
--------------------------------------------------------------------------------
1 | # Two Fer
2 |
3 | `Two-fer` or `2-fer` is short for two for one. One for you and one for me.
4 |
5 | Given a name, return a string with the message:
6 |
7 | ```text
8 | One for X, one for me.
9 | ```
10 |
11 | Where X is the given name.
12 |
13 | However, if the name is missing, return the string:
14 |
15 | ```text
16 | One for you, one for me.
17 | ```
18 |
19 | Here are some examples:
20 |
21 | |Name | String to return
22 | |:------:|:-----------------:
23 | |Alice | One for Alice, one for me.
24 | |Bob | One for Bob, one for me.
25 | | | One for you, one for me.
26 | |Zaphod | One for Zaphod, one for me.
27 | ## Source
28 |
29 | [https://github.com/exercism/problem-specifications/issues/757](https://github.com/exercism/problem-specifications/issues/757)
30 |
31 | ## Submitting Incomplete Solutions
32 | It's possible to submit an incomplete solution so you can see how others have completed the exercise.
33 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/two-fer/project.clj:
--------------------------------------------------------------------------------
1 | (defproject two-fer "0.1.0-SNAPSHOT"
2 | :description "two-fer exercise."
3 | :url "https://github.com/exercism/clojure/tree/master/exercises/two-fer"
4 | :dependencies [[org.clojure/clojure "1.8.0"]])
5 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/two-fer/src/two_fer.clj:
--------------------------------------------------------------------------------
1 | (ns two-fer)
2 |
3 | (defn two-fer
4 | ([] "One for you, one for me.")
5 | ([name] (str "One for " name ", one for me.")))
6 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/two-fer/target/classes/META-INF/maven/two-fer/two-fer/pom.properties:
--------------------------------------------------------------------------------
1 | #Leiningen
2 | #Sun Feb 03 05:19:15 BRST 2019
3 | groupId=two-fer
4 | artifactId=two-fer
5 | version=0.1.0-SNAPSHOT
6 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/two-fer/target/repl-port:
--------------------------------------------------------------------------------
1 | 62204
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/two-fer/target/stale/leiningen.core.classpath.extract-native-dependencies:
--------------------------------------------------------------------------------
1 | [{:dependencies {org.clojure/clojure {:vsn "1.8.0", :native-prefix nil}, nrepl {:vsn "0.5.3", :native-prefix nil}, nrepl/bencode {:vsn "1.0.0", :native-prefix nil}, clojure-complete {:vsn "0.2.5", :native-prefix nil}}, :native-path "target/native"} {:native-path "target/native", :dependencies {org.clojure/clojure {:vsn "1.8.0", :native-prefix nil, :native? false}, clojure-complete {:vsn "0.2.5", :native-prefix nil, :native? false}, nrepl {:vsn "0.5.3", :native-prefix nil, :native? false}, nrepl/bencode {:vsn "1.0.0", :native-prefix nil, :native? false}}}]
--------------------------------------------------------------------------------
/programming_challenges/exercism/clojure/two-fer/test/two_fer_test.clj:
--------------------------------------------------------------------------------
1 | (ns two-fer-test
2 | (:require [clojure.test :refer [deftest is]]
3 | two-fer))
4 |
5 | (deftest two-fer-test
6 | (is (= "One for you, one for me." (two-fer/two-fer))))
7 |
8 | (deftest name-alice-test
9 | (is (= "One for Alice, one for me." (two-fer/two-fer "Alice"))))
10 |
11 | (deftest name-bob-test
12 | (is (= "One for Bob, one for me." (two-fer/two-fer "Bob"))))
13 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/javascript/collatz-conjecture.js:
--------------------------------------------------------------------------------
1 | export const steps = n => {
2 | if (n <= 0) throw "Only positive numbers are allowed";
3 |
4 | let times = 0;
5 |
6 | while (n !== 1) {
7 | if (n % 2 === 0) {
8 | n /= 2;
9 | } else {
10 | n = n * 3 + 1;
11 | }
12 |
13 | times++;
14 | }
15 |
16 | return times;
17 | };
18 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/javascript/gigasecond.js:
--------------------------------------------------------------------------------
1 | const year = date => date.getUTCFullYear();
2 | const month = date => date.getUTCMonth();
3 | const day = date => date.getUTCDate() + 11574;
4 | const hours = date => date.getUTCHours() + 1;
5 | const minutes = date => date.getUTCMinutes() + 46;
6 | const second = date => date.getUTCSeconds() + 40;
7 |
8 | export const gigasecond = date =>
9 | new Date(
10 | Date.UTC(
11 | year(date),
12 | month(date),
13 | day(date),
14 | hours(date),
15 | minutes(date),
16 | second(date)
17 | )
18 | );
19 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/javascript/hello-world.js:
--------------------------------------------------------------------------------
1 | export const hello = () => "Hello, World!";
2 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/javascript/leap.js:
--------------------------------------------------------------------------------
1 | // https://exercism.io/tracks/javascript/exercises/leap/solutions/0e7bcf1db4974d159ab9ebe9e961bcd1
2 |
3 | export const isLeap = year =>
4 | (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
5 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/javascript/resistor-color.js:
--------------------------------------------------------------------------------
1 | const colorCode = color => COLORS.indexOf(color);
2 |
3 | const COLORS = [
4 | "black",
5 | "brown",
6 | "red",
7 | "orange",
8 | "yellow",
9 | "green",
10 | "blue",
11 | "violet",
12 | "grey",
13 | "white"
14 | ];
15 |
16 | export { colorCode, COLORS };
17 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/javascript/resistor-colors.js:
--------------------------------------------------------------------------------
1 | // https://exercism.io/my/solutions/0a95e6a8ebb94efeac42b2c6e065818b
2 |
3 | const COLORS = [
4 | "black",
5 | "brown",
6 | "red",
7 | "orange",
8 | "yellow",
9 | "green",
10 | "blue",
11 | "violet",
12 | "grey",
13 | "white"
14 | ];
15 |
16 | const reducer = (acc, resistanceValue) => acc + resistanceValue;
17 | const resistanceValuesString = (resistorsColors) =>
18 | resistorsColors
19 | .map((color) => COLORS.indexOf(color))
20 | .reduce(reducer, "");
21 |
22 | export const value = (resistorsColors) => {
23 | return Number(resistanceValuesString(resistorsColors));
24 | };
25 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/javascript/reverse-string.js:
--------------------------------------------------------------------------------
1 | const lastChar = str => str[str.length - 1];
2 |
3 | export const reverseString = str => {
4 | if (str.length <= 1) {
5 | return str;
6 | }
7 |
8 | return lastChar(str) + reverseString(str.substring(0, str.length - 1));
9 | };
10 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/javascript/triangle.js:
--------------------------------------------------------------------------------
1 | export function Triangle(side1, side2, side3) {
2 | this.side1 = side1;
3 | this.side2 = side2;
4 | this.side3 = side3;
5 | }
6 |
7 | Triangle.prototype.isEquilateral = function() {
8 | return this.side1 == this.side2 && this.side1 == this.side3;
9 | };
10 |
11 | Triangle.prototype.isIsosceles = function() {
12 | return (
13 | this.side1 == this.side2 ||
14 | this.side1 == this.side3 ||
15 | this.side2 == this.side3
16 | );
17 | };
18 |
19 | Triangle.prototype.anyNonPositiveSide = function() {
20 | return this.side1 <= 0 || this.side2 <= 0 || this.side3 <= 0;
21 | };
22 |
23 | Triangle.prototype.isInequality = function() {
24 | return (
25 | this.side1 > this.side2 + this.side3 ||
26 | this.side2 > this.side1 + this.side3 ||
27 | this.side3 > this.side2 + this.side1
28 | );
29 | };
30 |
31 | Triangle.prototype.kind = function() {
32 | if (this.anyNonPositiveSide() || this.isInequality()) {
33 | throw "Not a triangle";
34 | } else if (this.isEquilateral()) {
35 | return "equilateral";
36 | } else if (this.isIsosceles()) {
37 | return "isosceles";
38 | } else {
39 | return "scalene";
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/programming_challenges/exercism/javascript/two-fer.js:
--------------------------------------------------------------------------------
1 | export const twoFer = (name = "you") => `One for ${name}, one for me.`;
2 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/array_of_n_elements/array_of_n_elements.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-array-of-n-elements/problem
2 |
3 | (defn array-of-n-elements
4 | [n]
5 | (range n))
6 |
7 | (array-of-n-elements 1)
8 | (array-of-n-elements 3)
9 | (array-of-n-elements 5)
10 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/array_of_n_elements/array_of_n_elements_without_range.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-array-of-n-elements/problem
2 |
3 | (defn array-of-n-elements-without-range
4 | [n]
5 | (loop [n n list []]
6 | (if (pos? n)
7 | (recur (dec n) (conj list 0))
8 | list)))
9 |
10 | (array-of-n-elements-without-range 1)
11 | (array-of-n-elements-without-range 3)
12 | (array-of-n-elements-without-range 5)
13 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/basics/hello_world.clj:
--------------------------------------------------------------------------------
1 | ;; Problem: https://www.hackerrank.com/challenges/fp-hello-world/problem?h_r=next-challenge&h_v=zen
2 |
3 | (print "Hello World")
4 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/basics/hello_world_n_times.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-hello-world-n-times/problem
2 |
3 | (defn greater-than-zero? [n] (> n 0))
4 |
5 | (defn hello-word-n-times
6 | [n]
7 | (if (greater-than-zero? n)
8 | (do (println "Hello World")
9 | (hello-word-n-times (dec n)))))
10 |
11 | (hello-word-n-times 4)
12 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/basics/solve_me_first.clj:
--------------------------------------------------------------------------------
1 | ;; Problem: https://www.hackerrank.com/challenges/fp-solve-me-first/problem
2 |
3 | (defn solve-me-first
4 | [a b]
5 | (+ a b))
6 |
7 | (def a (read-line))
8 | (def b (read-line))
9 |
10 | (println (solve-me-first (Integer/parseInt a) (Integer/parseInt b)))
11 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/eval_ex/main.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/eval-ex/problem
2 |
3 | ;; Approach:
4 | ;; Use map to transform the list of 10 elements from x to (/ (exp x n) (factorial n))
5 | ;; And reduce suming each element
6 |
7 | ;; For this approach, we can separate in 3 different functions
8 | ;; - exp: exponantial
9 | ;; - factorial
10 | ;; - expansion: function composed of exp and factorial passed to map
11 |
12 | ;; So we can test these 3 functions
13 |
14 | (ns eval-ex
15 | (:use [clojure.test]))
16 |
17 | (defn exp
18 | [x n]
19 | (reduce * (repeat n x)))
20 |
21 | (defn factorial
22 | [n]
23 | (reduce * (range 1 (inc n))))
24 |
25 | (defn expansion
26 | [x]
27 | (fn [n]
28 | (/ (exp x n) (factorial n))))
29 |
30 | (defn series-expansion
31 | [x]
32 | (read-string
33 | (format "%.4f"
34 | (reduce + (map (expansion x) (range 10))))))
35 |
36 | ;; -----------------------------------------------------------
37 |
38 | ;; Tests
39 |
40 | (deftest test-exp
41 | (testing "Exponantial function"
42 | (is (= 1 (exp 1 0)))
43 | (is (= 1 (exp 1 1)))
44 | (is (= 4 (exp 2 2)))))
45 |
46 | (deftest test-factorial
47 | (testing "Factorial function"
48 | (is (= 1 (factorial 0)))
49 | (is (= 1 (factorial 1)))
50 | (is (= 120 (factorial 5)))))
51 |
52 | (deftest test-expansion
53 | (testing "Expansion function"
54 | (is (= 1 ((expansion 10) 0)))
55 | (is (= 10 ((expansion 10) 1)))
56 | (is (= 50 ((expansion 10) 2)))))
57 |
58 | (deftest test-series-expansion
59 | (testing "Sample Input - Output"
60 | (is (= 2423600.1887 (series-expansion 20.0000)))
61 | (is (= 143.6895 (series-expansion 5.0000)))
62 | (is (= 1.6487 (series-expansion 0.5000)))
63 | (is (= 0.6065 (series-expansion -0.5000)))))
64 |
65 | (run-tests)
66 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/fibonacci/fibonacci.js:
--------------------------------------------------------------------------------
1 | // https://www.hackerrank.com/challenges/functional-programming-warmups-in-recursion---fibonacci-numbers/problem
2 |
3 | const fibonacci = n => {
4 | if (n === 1) return 0;
5 | if (n === 2) return 1;
6 | return fibonacci(n - 1) + fibonacci(n - 2);
7 | }
8 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/filter_array/filter_array.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-filter-array/problem
2 |
3 | (defn filter-array
4 | [n lst]
5 | (filter #(> n %) lst))
6 |
7 | (filter-array 25 [-41 46 -28 21 52 83 -29 84 27 40])
8 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/filter_positions_in_a_list/filter_positions_in_a_list.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-filter-positions-in-a-list/problem
2 |
3 | (defn filter-positions-in-a-list
4 | [lst]
5 | (take-nth 2 (rest lst)))
6 |
7 | (filter-positions-in-a-list [])
8 | (filter-positions-in-a-list [0 1 2])
9 | (filter-positions-in-a-list [0 1 2 3 4 5 6 7 8 9])
10 | (filter-positions-in-a-list [8 15 22 1 10 6 2 18 18 1])
11 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/list_length/list_length.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-list-length/problem?h_r=next-challenge&h_v=zen
2 |
3 | (defn list-length
4 | [lst]
5 | (loop [coll lst counter 0]
6 | (if (empty? coll)
7 | counter
8 | (recur (rest coll) (inc counter)))))
9 |
10 | (list-length [0 1 2 3 4 5 6 7 8 9])
11 | (list-length [0 1 2 -1 4 -5 6 7 -8 9])
12 | (list-length [])
13 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/list_length/list_length_reduce.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-list-length/problem?h_r=next-challenge&h_v=zen
2 |
3 | (defn list-length
4 | [lst]
5 | (reduce + (map (constantly 1) lst)))
6 |
7 | (list-length [0 1 2 3 4 5 6 7 8 9])
8 | (list-length [0 1 2 -1 4 -5 6 7 -8 9])
9 | (list-length [])
10 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/list_replication/list_replication.clj:
--------------------------------------------------------------------------------
1 | ;; Problem: https://www.hackerrank.com/challenges/fp-list-replication/problem
2 |
3 | (defn list-replication
4 | [n list]
5 | (sort
6 | (flatten
7 | (repeat n list))))
8 |
9 | (list-replication 3 [1 2 3])
10 | (list-replication 2 [4 5])
11 | (list-replication 1 [10 100])
12 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/reverse_a_list/reverse_a_list.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-reverse-a-list/problem
2 | ;; last function: returns the last element of a collection
3 | ;; count function: returns the length of a collection
4 | ;; take function: returns the first N taken elements of a collection
5 | ;; not-empty function: returns true if the collection is not empty. Otherwise, false
6 |
7 | (def example-list [19 22 3 28 26 17 18 4 28 0])
8 |
9 | (defn reverse-a-list
10 | [list]
11 | (loop [original-list list reversed-list []]
12 | (if (not-empty original-list)
13 | (recur (take (dec (count original-list)) original-list) (conj reversed-list (last original-list)))
14 | reversed-list)))
15 |
16 | (reverse-a-list example-list)
17 |
18 | ;; Implementing an anonymous function
19 |
20 | (fn [lst]
21 | (loop [original-list lst reversed-list []]
22 | (if (not-empty original-list)
23 | (recur (take (dec (count original-list)) original-list) (conj reversed-list (last original-list)))
24 | reversed-list)))
25 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/reverse_a_list/reverse_a_list_into.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-reverse-a-list/problem
2 | ;; basically, the into function is a reduce + conj
3 |
4 | (def example-list [19 22 3 28 26 17 18 4 28 0])
5 |
6 | (defn reverse-a-list
7 | [lst]
8 | (into '() lst))
9 |
10 | (reverse-a-list example-list)
11 |
12 | ((fn [lst] (into '() lst)) example-list)
13 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/reverse_a_list/reverse_a_list_reduce.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-reverse-a-list/problem
2 |
3 | (def example-list [19 22 3 28 26 17 18 4 28 0])
4 |
5 | (defn reverse-a-list
6 | [lst]
7 | (reduce conj '() lst))
8 |
9 | (reverse-a-list example-list)
10 |
11 | ;; Implementing an anonymous function
12 |
13 | ((fn [lst] (reduce conj '() lst)) example-list)
14 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/sum_of_odd_elements/sum_of_odd_elements.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-sum-of-odd-elements/problem
2 |
3 | (defn sum-of-odd-elements
4 | [lst]
5 | (reduce
6 | +
7 | (filter
8 | (odd? n)
9 | lst)))
10 |
11 | (sum-of-odd-elements [3 2 4 6 5 7 8 0 1])
12 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/update_list/update_list.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-update-list/problem
2 |
3 | (defn to-absolute
4 | [n]
5 | (if (neg? n)
6 | (+ (* n -2) n)
7 | n))
8 |
9 | (defn add-element-from-list-to-list
10 | [lst1 lst2]
11 | (conj lst2 (to-absolute (first lst1))))
12 |
13 | (defn update-list
14 | [lst]
15 | (loop [original-list lst absolute-list []]
16 | (if (empty? original-list)
17 | absolute-list
18 | (recur
19 | (rest original-list)
20 | (add-element-from-list-to-list original-list absolute-list)))))
21 |
22 | (update-list [])
23 | (update-list [1 2 3 4 5])
24 | (update-list [-1 -2 -3 -4 -5])
25 | (update-list [1 -2 3 -4 5])
26 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/update_list/update_list_anonymous.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-update-list/problem
2 |
3 | (fn
4 | [lst]
5 | (loop [original-list lst absolute-list []]
6 | (if (empty? original-list)
7 | absolute-list
8 | (recur
9 | (rest original-list)
10 | (conj
11 | absolute-list
12 | (if (< (first original-list) 0)
13 | (+ (* (first original-list) -2) (first original-list))
14 | (first original-list)))))))
15 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/update_list/update_list_map.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-update-list/problem
2 |
3 | (defn to-absolute
4 | [n]
5 | (if (neg? n)
6 | (+ (* n -2) n)
7 | n))
8 |
9 | (defn update-list-map
10 | [lst]
11 | (map to-absolute lst))
12 |
13 | (update-list-map [])
14 | (update-list-map [1 2 3 4 5])
15 | (update-list-map [-1 -2 -3 -4 -5])
16 | (update-list-map [1 -2 3 -4 5])
17 |
--------------------------------------------------------------------------------
/programming_challenges/hacker_rank/update_list/update_list_map_anonymous.clj:
--------------------------------------------------------------------------------
1 | ;; https://www.hackerrank.com/challenges/fp-update-list/problem
2 |
3 | (fn
4 | [lst]
5 | (map
6 | (fn
7 | [n]
8 | (if (neg? n)
9 | (+ (* n -2) n)
10 | n))
11 | lst))
12 |
--------------------------------------------------------------------------------
/programming_challenges/playground/collisions.clj:
--------------------------------------------------------------------------------
1 | (ns collisions.core
2 | (:require [clojure.string :as str])
3 | (:gen-class))
4 |
5 | (defn str->edge [s]
6 | (->> (str/split s #" ")
7 | (map #(Integer/parseInt %))))
8 |
9 | (defn file-contents->edges [s]
10 | (->> (str/split s #"\n")
11 | (map str->edge)))
12 |
13 | (defn edge->adj-list [[u v]]
14 | {u #{v}, v #{u}})
15 |
16 | (defn with-new-connections [adj-list new-connections]
17 | (merge-with into adj-list new-connections))
18 |
19 | (defn with-new-edge [adj-list edge]
20 | (->> (edge->adj-list edge)
21 | (with-new-connections adj-list)))
22 |
23 | (defn edges->adj-list [edges]
24 | (reduce with-new-edge {} edges))
25 |
26 | (defn same-network? [a b adj-list]
27 | (loop [[curr & rest] (list a), visited? #{}]
28 | (when curr
29 | (or (= curr b)
30 | (recur (->> (adj-list curr)
31 | (filter (complement visited?))
32 | (into rest))
33 | (conj visited? curr))))))
34 |
35 | (defn -main
36 | [file-path a b]
37 | (if (-> (slurp file-path)
38 | file-contents->edges
39 | edges->adj-list
40 | (->> (same-network? (Integer/parseInt a) (Integer/parseInt b))))
41 | (println "yup")
42 | (println "nah")))
43 |
--------------------------------------------------------------------------------
/programming_challenges/playground/jobs/job.clj:
--------------------------------------------------------------------------------
1 | ;; -- jobs and agents definition --
2 | (def jobs
3 | [{:id "f26e890b-df8e-422e-a39c-7762aa0bac36" :type "rewards-question" :urgent false}
4 | {:id "690de6bc-163c-4345-bf6f-25dd0c58e864" :type "bills-questions" :urgent false}
5 | {:id "c0033410-981c-428a-954a-35dec05ef1d2" :type "bills-questions" :urgent true}])
6 |
7 | (def agents
8 | [{:id "8ab86c18-3fae-4804-bfd9-c3d6e8f66260"
9 | :name "BoJack Horseman"
10 | :primary_skillset ["bills-questions"]
11 | :secondary_skillset []}
12 | {:id "ed0e23ef-6c2b-430c-9b90-cd4f1ff74c88"
13 | :name "Mr. Peanut Butter"
14 | :primary_skillset ["rewards-question"]
15 | :secondary_skillset ["bills-questions"]}])
16 | ;; -- end of jobs and agents definition --
17 |
18 | ;; -- sorting by urgency --
19 | (defn prioritize
20 | [jobs]
21 | (sort-by (complement :urgent) jobs))
22 |
23 | (prioritize jobs)
24 | ;; -- end of sorting by urgency --
25 |
26 | ;; -- filtering by skillsets --
27 | (def first-job (first jobs))
28 | (def second-job (second jobs))
29 |
30 | (defn by-skillset
31 | [job agent]
32 | (or
33 | (some #(= (:type job) %) (:primary_skillset agent))
34 | (some #(= (:type job) %) (:secondary_skillset agent))))
35 |
36 | (defn filter-by-skillset
37 | [agents job]
38 | (filter (partial by-skillset job) agents))
39 | ;; -- end of filtering by skillsets --
40 |
41 | ;; -- examples of function use --
42 | (filter-by-skillset agents first-job)
43 | (filter-by-skillset agents second-job)
44 | (filter-by-skillset (conj agents {:id "123" :name "Mr. Nothing" :primary_skillset ["nothing-other"] :secondary_skillset ["nothing"]}) second-job)
45 | ;; -- end of examples of function use --
46 |
47 | ;; -- sorting by job type --
48 | (defn agent-has-job-type-as-primary-skillset?
49 | [job-type agent]
50 | (if (some #{job-type} (:primary_skillset agent)) 0 1))
51 |
52 | (defn add-contains-primary-skillset
53 | [job-type agent]
54 | (assoc
55 | agent
56 | :contains-primary-skillset?
57 | (agent-has-job-type-as-primary-skillset? job-type agent)))
58 |
59 | (defn remove-contains-primary-skillset
60 | [agent]
61 | (dissoc agent :contains-primary-skillset?))
62 |
63 | (defn sort-agents-by-primary-skillset
64 | [agents job]
65 | (->> agents
66 | (map (partial add-contains-primary-skillset (:type job)))
67 | (sort-by :contains-primary-skillset?)
68 | (map remove-contains-primary-skillset)))
69 |
70 | (defn agents-to-be-assigned
71 | [agents job]
72 | (-> agents
73 | (filter-by-skillset job)
74 | (sort-agents-by-primary-skillset job)))
75 |
76 | (defn agents-ids
77 | [assigned-jobs]
78 | (map
79 | #(get-in % [:job_assigned :agent_id])
80 | assigned-jobs))
81 |
82 | (defn find-agent-id?
83 | [assigned-jobs agent]
84 | (some
85 | #(= (:id agent) %)
86 | (agents-ids assigned-jobs)))
87 |
88 | (defn assigned?
89 | [assigned-jobs agent]
90 | (find-agent-id? assigned-jobs agent))
91 |
92 | (defn not-assigned?
93 | [assigned-jobs agent]
94 | ((complement assigned?) assigned-jobs agent))
95 |
96 | (defn make-agent-job-assignment
97 | [job agent]
98 | {:job_assigned
99 | {:job_id (:id job)
100 | :agent_id (:id agent)}})
101 |
102 | (defn assignments
103 | [assigned-jobs job new-assignment]
104 | (if (nil? new-assignment)
105 | assigned-jobs
106 | (conj
107 | assigned-jobs
108 | (make-agent-job-assignment
109 | job
110 | new-assignment))))
111 |
112 | (defn assign-agent
113 | [agents job assigned-jobs]
114 | (->> (agents-to-be-assigned agents job)
115 | (filter (partial not-assigned? assigned-jobs))
116 | (first)
117 | (assignments assigned-jobs job)))
118 |
119 | ;; ----- Testing sorted agents -----
120 | (defn testing [agents jobs assigned-jobs]
121 | (loop
122 | [agents agents
123 | jobs (prioritize jobs)
124 | assigned-jobs assigned-jobs]
125 |
126 | (if (not-empty jobs)
127 | (do
128 | (println (str "----- " (:type (first jobs)) " -----"))
129 | (recur
130 | agents
131 | (rest jobs)
132 | (assign-agent agents (first jobs) assigned-jobs)))
133 |
134 | assigned-jobs)))
135 |
136 | (pprint (testing agents jobs []))
137 | ;; ----- end of Testing sorted agents -----
138 |
--------------------------------------------------------------------------------
/programming_challenges/playground/jobs/resource/input.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "new_agent": {
4 | "id": "8ab86c18-3fae-4804-bfd9-c3d6e8f66260",
5 | "name": "BoJack Horseman",
6 | "primary_skillset": [
7 | "bills-questions"
8 | ],
9 | "secondary_skillset": []
10 | }
11 | },
12 | {
13 | "new_job": {
14 | "id": "f26e890b-df8e-422e-a39c-7762aa0bac36",
15 | "type": "rewards-question",
16 | "urgent": false
17 | }
18 | },
19 | {
20 | "new_agent": {
21 | "id": "ed0e23ef-6c2b-430c-9b90-cd4f1ff74c88",
22 | "name": "Mr. Peanut Butter",
23 | "primary_skillset": [
24 | "rewards-question"
25 | ],
26 | "secondary_skillset": [
27 | "bills-questions"
28 | ]
29 | }
30 | },
31 | {
32 | "new_job": {
33 | "id": "690de6bc-163c-4345-bf6f-25dd0c58e864",
34 | "type": "bills-questions",
35 | "urgent": false
36 | }
37 | },
38 | {
39 | "new_job": {
40 | "id": "c0033410-981c-428a-954a-35dec05ef1d2",
41 | "type": "bills-questions",
42 | "urgent": true
43 | }
44 | },
45 | {
46 | "job_request": {
47 | "agent_id": "8ab86c18-3fae-4804-bfd9-c3d6e8f66260"
48 | }
49 | },
50 | {
51 | "job_request": {
52 | "agent_id": "ed0e23ef-6c2b-430c-9b90-cd4f1ff74c88"
53 | }
54 | }
55 | ]
56 |
--------------------------------------------------------------------------------
/programming_challenges/playground/jobs/resource/output.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "job_assigned": {
4 | "job_id": "c0033410-981c-428a-954a-35dec05ef1d2",
5 | "agent_id": "8ab86c18-3fae-4804-bfd9-c3d6e8f66260"
6 | }
7 | },
8 | {
9 | "job_assigned": {
10 | "job_id": "f26e890b-df8e-422e-a39c-7762aa0bac36",
11 | "agent_id": "ed0e23ef-6c2b-430c-9b90-cd4f1ff74c88"
12 | }
13 | }
14 | ]
15 |
--------------------------------------------------------------------------------
/python/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Python Resources
4 |
5 | ## Posts
6 |
7 | - [Python funcional: Quase um livro, quase um tutorial](https://github.com/dunossauro/python-funcional)
8 | - [Learn Functional Python in 10 Minutes](https://hackernoon.com/learn-functional-python-in-10-minutes-to-2d1651dece6f)
9 | - [Introduction to Functional Programming in Python](https://www.dataquest.io/blog/introduction-functional-programming-python/)
10 | - [A practical introduction to functional programming in Python](https://maryrosecook.com/blog/post/a-practical-introduction-to-functional-programming)
11 | - [Official Functional Programming HOWTO](https://docs.python.org/3/howto/functional.html)
12 | - [Immutable data structures in Python](https://www.theguardian.com/info/developer-blog/2014/oct/21/immutable-data-structures-in-python)
13 | - [Best Practices for Using Functional Programming in Python](https://kite.com/blog/python/functional-programming)
14 |
15 | ## Talks
16 |
17 | - [Immutable Programming Writing Functional Python](https://www.youtube.com/watch?v=_OLEVvjrIj8&ab_channel=PyCon2017)
18 |
19 | ## Books
20 |
21 | - [Functional Programming in Python](https://www.oreilly.com/programming/free/files/functional-programming-python.pdf)
22 |
23 |
24 |
--------------------------------------------------------------------------------
/python/intro.py:
--------------------------------------------------------------------------------
1 | # Assign functions to a variable
2 | def add(a, b):
3 | return a + b
4 |
5 |
6 | plus = add
7 | value = plus(1, 2)
8 | print(value) # 3
9 |
10 | # Lambda
11 | value = (lambda a, b: a + b)(1, 2)
12 | print(value) # 3
13 |
14 | addition = lambda a, b: a + b
15 | value = addition(1, 2)
16 | print(value) # 3
17 |
18 | authors = [
19 | 'Octavia Butler',
20 | 'Isaac Asimov',
21 | 'Neal Stephenson',
22 | 'Margaret Atwood',
23 | 'Usula K Le Guin',
24 | 'Ray Bradbury'
25 | ]
26 |
27 | sorted_authors_by_name_length = sorted(authors, key=len)
28 | print(sorted_authors_by_name_length)
29 |
30 | sorted_authors_by_last_name = sorted(authors, key=lambda name: name.split()[-1])
31 | print(sorted_authors_by_last_name)
32 |
--------------------------------------------------------------------------------
/ruby/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Ruby Resources
4 |
5 | - [Programação funcional que funciona por Rodrigo Serradura](https://www.youtube.com/watch?v=w1OwYWe4UFo&ab_channel=GURUSPtalks)
6 | - [Programação funcional com Ruby, potencialize e simplifique qualquer codebase](https://speakerdeck.com/serradura/programacao-funcional-com-ruby-potencialize-e-simplifique-qualquer-codebase?slide=126)
7 | - [Ruby Functional Programming](https://github.com/tokland/tokland/wiki/RubyFunctionalProgramming)
8 | - [Applications of Lambda in Ruby](http://jetrockets.pro/blog/lambda)
9 | - [What’s new in Ruby 2.6?](https://medium.com/tailor-tech/whats-new-in-ruby-2-6-a4774f3631c1)
10 | - [Using `yield_self` for composable ActiveRecord relations](https://robots.thoughtbot.com/using-yieldself-for-composable-activerecord-relations)
11 | - [yield_self is more awesome than you could think](https://zverok.github.io/blog/2018-01-24-yield_self.html)
12 | - [Exploring Ruby 2.6 — Proc#compose and Enumerator#chain](https://medium.com/@baweaver/exploring-ruby-2-6-proc-compose-and-enumerator-chain-49f10e237542)
13 |
14 |
15 |
--------------------------------------------------------------------------------
/ruby/immutable_array.rb:
--------------------------------------------------------------------------------
1 | # Push: mutable
2 | list = [1, 2, 3]
3 | list.push(4)
4 | list # [1, 2, 3, 4]
5 |
6 | # <<: mutable
7 | list = [1, 2, 3]
8 | list << 4
9 | list # [1, 2, 3, 4]
10 |
11 | # +: immutable
12 | list = [1, 2, 3]
13 | list + [4] # [1, 2, 3, 4]
14 | list # [1, 2, 3]
15 |
--------------------------------------------------------------------------------
/ruby/immutable_select_with_reduce.rb:
--------------------------------------------------------------------------------
1 | def select(list, fn)
2 | list.reduce([]) { |acc, n| fn[n] ? acc + [n] : acc }
3 | end
4 |
5 | even = -> n { n % 2 == 0 }
6 | list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
7 |
8 | select(list, even) # [2, 4, 6, 8, 10]
--------------------------------------------------------------------------------
/rust/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Rust Functional Programming
4 |
5 | ## Table of Content
6 |
7 | - [General](#general)
8 | - [Books](#books)
9 |
10 | ## General
11 |
12 | - [Functional Language Features: Iterators and Closures](https://doc.rust-lang.org/book/ch13-00-functional-features.html)
13 |
14 | ## Books
15 |
16 | - [Programação Funcional e Concorrente em Rust](https://www.casadocodigo.com.br/products/livro-rust-funcional-concorrente)
17 |
18 |
19 |
--------------------------------------------------------------------------------