fix(guide): simplify directory structure

This commit is contained in:
Mrugesh Mohapatra
2018-10-16 21:26:13 +05:30
parent f989c28c52
commit da0df12ab7
35752 changed files with 0 additions and 317652 deletions

View File

@ -0,0 +1,15 @@
---
title: Clojure Collections
---
One of Clojure's main positives is that it has quite a few different kinds of sequence: vectors, lists, hashmaps, _oh my!_ And each different type of collection has its own upsides, downsides, and a whole host of useful functions that operate on them.
To understand the differences between each type of collection, when to use each one, and how to convert between them all, it may be necessary to check out other types of collection and remind yourself what makes them special.
As such, this page serves as an index so you can easily view any of the articles about data structures.
* <a href='http://forum.freecodecamp.com/t/clojure-lists-they-are-everything/18417' target='_blank' rel='nofollow'>Lists</a>
* <a href='http://forum.freecodecamp.com/t/clojure-vectors/18421' target='_blank' rel='nofollow'>Vectors</a>
* <a href='http://forum.freecodecamp.com/t/clojure-hashmaps/18414' target='_blank' rel='nofollow'>Hashmaps</a>
| [![:point_left:](/images/emoji/emoji_one/point_left.png?v=2 ":point_left:") Previous](http://forum.freecodecamp.com/t/clojure-more-on-functions/18413) | [![:book:](/images/emoji/emoji_one/book.png?v=2 ":book:") Home ![:book:](/images/emoji/emoji_one/book.png?v=2 ":book:")](http://forum.freecodecamp.com/t/clojure-resources/18422) | [Next ![:point_right:](/images/emoji/emoji_one/point_right.png?v=2 ":point_right:")](http://forum.freecodecamp.com/t/clojure-lists-they-are-everything/18417)|
| <a href='http://forum.freecodecamp.com/t/clojure-more-on-functions/18413' target='_blank' rel='nofollow'>More on Functions</a> | <a href='http://forum.freecodecamp.com/t/clojure-resources/18422' target='_blank' rel='nofollow'>Table of Contents</a> | <a href='http://forum.freecodecamp.com/t/clojure-lists-they-are-everything/18417' target='_blank' rel='nofollow'>Lists</a>|

View File

@ -0,0 +1,128 @@
---
title: Clojure Conditionals
---
You're not going to get anywhere in a language if all you can do is define functions that print things and do simple arithmetic. Conditionals and logic are a fundamental part of making code that does interesting, useful things. Try and imagine a world without logic in programs: you wouldn't even be able to simple things, like checking if two numbers are equal!
## Logical Operators
Clojure, like most languages, has 3 logical operators: `and`, `or` and `not`. These functions take booleans (`true` or `false`) as arguments, and return booleans based on what those booleans are. Like everything in a Lisp, these operators use prefix notation, which means they might look weird to you.
(and true false)
; => false
(and true true)
; => true
(or false false)
; => false
(or true false)
; => true
(not true)
; => false
(not false)
; => true
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/XfXn8T' target='_blank' rel='nofollow'>IDEOne it!</a>
## If
`if` allows you to execute code based on whether a boolean is `true` or `false`. `if` in Clojure looks quite weird, not because it uses prefix notation, but because there is no else keyword. If the condition is true, it evaluates the first expression. If it's false, it executes the second.
(if (= (+ 2 2) 4)
(println "Maths works!") ; this gets evaluated if 2 + 2 = 4
(println "UH OH")) ; this gets evaluated if 2 + 2 != 4
; => Maths works!
; nil
This presents a problem: what if we want to do multiple things?
(if (= (+ 2 2) 4)
(println "Maths works!")
(println "Maths still works!")
(println "UH OH"))
; => CompilerException java.lang.RuntimeException: Too many arguments to if
Thankfully, we have the `do` function to solve this problem. `do` evaluates multiple expressions, one after the other.
(if (= (+ 2 2) 4)
(do ; all of this gets evaluated if 2 + 2 = 4
(println "Maths works!")
(println "Maths still works!"))
(println "UH OH"))
; => Maths works!
; Maths still works!
; nil
**Note:** since `if` is, itself, an expression, there's no need for a ternary operator like in many C-like languages.
var doesMathsWork = 2 + 2 === 4 ? "Maths works!" : "UH OH";
console.log(doesMathsWork);
// => Maths works!
Now that you've seen how it works, it doesn't look so weird right? This is much easier to read and understand (ignoring the lack of the word `else`):
(def does-maths-work (if (= (+ 2 2) 4) "Maths works!" "UH OH"))
(println does-maths-work)
; => Maths works!
; nil
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/5XhcAa' target='_blank' rel='nofollow'>IDEOne it!</a>
## Alternatives to If
Clojure also has some macros that behave similarly to `if`, and can sometimes be more concise.
`if-not` is perhaps the most simple example - it's `if` inverted. These two pieces of code are exactly the same:
(def does-maths-work (if (not (= (+ 2 2) 4)) "UH OH" "Maths works!"))
(def does-maths-work (if-not (= (+ 2 2) 4) "UH OH" "Maths works!"))
The first expression gets evaluated if it's false, and the second gets evaluated if it's true. Notice that using `if-not` avoids nesting our condition inside `not`, which can help make our code easier to understand.
`when` is another useful macro. These two pieces of code are also the same:
(if (= (+ 2 2) 4) (do (println "Maths works!") (println "Hooray!")))
(when (= (+ 2 2) 4) (println "Maths works!") (println "Hooray!"))
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/tUVAw3' target='_blank' rel='nofollow'>IDEOne it!</a>
**Note:** There is no `when/else`. `when` _only_ executes if the condition is true.
`cond` allows you to combine many conditions into a single expression. It takes a sequence of logical expression and expression pairs and evaluate each logical expression in order. When it finds a logical expression that evaluates to `true`, it evaluates the second expression of the pair. After this, no other expressions are evaluated. This behavior is like short-circuit logic in Javascript.
(cond (= 0 1) "I'm paired with a false expression and I don't evalute.."
(= 1 1) "I'm the first expression paired with a true expression!"
(= 2 2) "I don't evalute even though I'm also paired with true ;_;"
:else "I evaluate if no other boolean expressions evaluate to true")
; => "I'm the first expression paired with a true expression!"
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/zu5RCq' target='_blank' rel='nofollow'>IDEOne it!</a>
The `:else` keyword can be used in place of a logical expression in the last expression pair in `cond`. It signifies that it's corresponding expression should be evaluated if all other boolean expressions evaluate to false. It is the same as putting `true` as the last boolean expression.
## Special Forms and Evalution
You may have noticed that the rules of evaluating conditional expressions is a bit different from other expressions. Conditional expression are a part of a group of expressions called _special forms_. This means that they don't follow normal Clojure evaluation rules.
As you now know, a conditional expression only evaluates the subexpression that corresponds to the boolean result. This means that invalid code within a conditional expression won't be evaluated in some cases. Consider the two `if` expressions below. Although `(+ 1 "failure")` is an invalid expression, Clojure only raises an exception when the condition is `false`.
(if true "sucess" (+ 1 "failure"))
; => "sucess"
(if false "sucess" (+ 1 "failure"))
; => ClassCastException java.lang.String cannot be cast to java.lang.Number ...
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/n4Ug2S' target='_blank' rel='nofollow'>IDEOne it!</a>
Compare this with the behavior of `my-if` defined below:
(defn my-if [condition true-case false-case]
(if condition true-case false-case))
(my-if true "sucess" (+ 1 "failure"))
; => ClassCastException java.lang.String cannot be cast to java.lang.Number ...
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/U7cVI4' target='_blank' rel='nofollow'>IDEOne it!</a>
`my-if` is a function with normal evaluation rules, so all of it's subexpressions must be evaluted before it can be evaluted.
Clojure has plenty of useful macros like these for all kinds of tasks. Try having a look at <a href='https://clojuredocs.org/' target='_blank' rel='nofollow'>the Clojure documentation</a> and see if you can find any more!
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ":point_left:") Previous](//forum.freecodecamp.com/t/clojure-the-basics/18410) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:") Home ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [Next ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ":point_right:")](//forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415)|
| [Summary](//forum.freecodecamp.com/t/clojure-the-basics/18410) | [Table of Contents](//forum.freecodecamp.com/t/clojure-resources/18422) | [Conditionals](//forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415)|

View File

@ -0,0 +1,54 @@
---
title: Clojure Create Local Variables with Let
---
`let` is a fundamental part of Clojure. Whereas `def` creates a global variable, `let` creates a local variable.
(def x 5)
(println x)
; => 5
; nil
(let [x 2]
(println x))
; => 2
; nil
(println x)
; => 5
; nil
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/xcNth2' target='_blank' rel='nofollow'>IDEOne it!</a>
`x` in this example never actually gets changed. `x` just refers to something different inside of our `let` binding. This can be a useful way to avoid repetition inside a function.
This is incredibly useful. Having too many global variables can lead to nasty bugs and unintended behaviour.
(def x 5)
(defn add-5 [y] (+ x y))
(add-5 5)
; => 10
(defn change-x []
(def x 6))
(change-x)
; => nil
(add-5 5)
; => 11
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/MFjA3C' target='_blank' rel='nofollow'>IDEOne it!</a>
Uh oh! That's not adding 5 anymore! Of course, this example is a bit silly, but using too many global variables can lead to bugs that are just as scary as this one.
**Note:** We aren't really _reassigning_ `x` here, like you would in a C-like language. We're just creating a new variable that happens to also be called x. This is a _very, very, **very**_ bad idea.
## Multiple Bindings
`let` can also define multiple variables at once, and can assign variables to expressions.
(let [spam "foo"
ham (str "b" "ar")] ; str is a function that concatenates strings
(println spam ham)) ; or converts variables into strings.
; => foo bar
; nil
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/y5EBIM' target='_blank' rel='nofollow'>IDEOne it!</a>
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ":point_left:") Previous](//forum.freecodecamp.com/t/clojure-conditionals/18412) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:") Home ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [Next ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ":point_right:")](//forum.freecodecamp.com/t/clojure-loop-recur/18418)|
| [Conditionals](//forum.freecodecamp.com/t/clojure-conditionals/18412) | [Table of Contents](//forum.freecodecamp.com/t/clojure-resources/18422) | [Loop and Recur](//forum.freecodecamp.com/t/clojure-loop-recur/18418)|

View File

@ -0,0 +1,95 @@
---
title: Clojure Hashmaps
---
A hashmap is a collection that maps keys to values. They have various names in other languages; Python refers to them as dictionaries, and Javascript's objects essentially work like hashmaps.
A hashmap can, like many collections, be constructed in two ways. There is the constructor function:
;; Note that each argument is *prepended* to the hashmap, not appended.
(def a-hashmap (hash-map :a 1 :b 2 :c 3))
a-hashmap
; => {:c 3, :b 2, :a 1}
You can also define them using a hashmap literal. This is often more concise and clear. Using commas to separate key/value pairs in hashmaps is recommended, as it can make the boundaries more clear.
;; This hashmap is actually in the right order, unlike the one above.
(def another-hashmap {:a 1, :b 2, :c 3})
another-hashmap
; => {:a 1, :b 2, :c 3}
## Keywords and retrieving values from hashmaps
Hold up. What is this? `:a`? `:b`? `:c`? Those look odd. Those, you see, are keywords. They're called _key_-words because they're often used as keys in hashmaps.
Why are they often used as keys? Well, unlike strings, keywords can be used as functions to extract values from a hashmap; no need for `get` or `nth`!
(def string-hashmap {"a" 1, "b" 2, "c" 3})
("a" string-hashmap)
; => ClassCastException java.lang.String cannot be cast to clojure.lang.IFn
(def keyword-hashmap {:a 1, :b 2, :c 3})
(:a keyword-hashmap)
; => 1
;; You can also pass a keyword a default value in case it's not found, just like get.
(:not-in-the-hashmap keyword-hashmap "not found!")
; => "not found!"
## Converting other collections to hashmaps
Converting to a hashmap is tricky. To demonstrate, let's try using it like `vec` or `seq`.
(hash-map [:a 1 :b 2 :c 3])
; => IllegalArgumentException No value supplied for key: [:a 1 :b 2 :c 3]
The `hash-map` function thinks that we're trying to create a hashmap with `[:a 1 :b 2 :c 3]` as one of the keys. Watch what happens if we give it the right number of arguments:
(hash-map [:a 1 :b 2 :c 3] "foo")
; => {[:a 1 :b 2 :c 3] "foo"}
To convert a sequence to a hashmap, you'll need to use and understand `apply`. Luckily, this is pretty simple: `apply` essentially destructures a collection before applying a function to it.
;; These two expressions are exactly the same.
(+ 1 2 3)
; => 6
(apply + [1 2 3])
; => 6
This is how you would convert a vector to a hashmap:
(apply hash-map [:a 1 :b 2 :c 3])
; => {:c 3, :b 2, :a 1}
;; This is the same as:
(hash-map :a 1 :b 2 :c 3)
; => {:c 3, :b 2, :a 1}
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/k9cOjo' target='_blank' rel='nofollow'>IDEOne it!</a>
## Update a hashmap
You can update values inside a hashmap using `assoc`. This allows you to append new key/value pairs or change old ones.
(def outdated-hashmap {:a 1, :b 2, :c 3})
(def newer-hashmap (assoc outdated-hashmap :d 4))
newer-hashmap
; => {:a 1, :b 2, :c 3, :d 4}
(def newest-hashmap (assoc newer-hashmap :a 22))
newest-hashmap
; => {:a 22, :b 2, :c 3, :d 4}
;; Note that outdated-hashmap has not been mutated by any of this.
;; Assoc is pure and functional.
outdated-hashmap
; => {:a 1, :b 2, :c 3}
## When to use a hashmap?
A hashmap is useful when you want to give names to your variables. If you're ever thinking to yourself, _"What if I used an object..."_ before you snap out of it and realise you're using Clojure, try using a hashmap.
They are also useful if you want to associate two different values with each other. Take, for example, a ROT13 cipher: you could associate `\A` with `\N`, `\B` with `\M`, etc. (This would be long and boring to write in most languages, but Clojure has some functions that can generate it for you and make it _fun!_)
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ":point_left:") Previous](//forum.freecodecamp.com/t/clojure-vectors/18421) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:") Home ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:")](//forum.freecodecamp.com/t/clojure-resources/18422) | Next ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ":point_right:") |
| [Vectors](//forum.freecodecamp.com/t/clojure-vectors/18421) | [Table of Contents](//forum.freecodecamp.com/t/clojure-resources/18422) | To Be Added |

View File

@ -0,0 +1,86 @@
---
title: Clojure
---
## Getting Started with Clojure
Before we begin, you may want to <a href='http://clojure.org/guides/getting_started' target='_blank' rel='nofollow'>install Clojure</a> and <a href='http://leiningen.org/#install' target='_blank' rel='nofollow'>Leiningen</a> (which is a tool for managing projects in Clojure). This will let you run Clojure in the command line using a REPL (Read-Evaluate-Print-Loop).
## Defining Variables
The bread and butter of any programming language are variables and functions. Let's define a variable!
(def our-string "Hello world!")
Easy peasy. That piece of code uses the `def` macro to associate a string (`"Hello world!"`) to a symbol (`our-string`). We could also have defined a number, such as `1` or `1.1`, a character, such as `\a` or `\Z`, or something more complicated like a list or a regular expression (_uuuugh_).
Note that our code is inside parentheses, like a list, because everything in a Lisp is a list! (That will be very important when we start talking about macros.)
## Defining Functions
Now, let's define a function!
(defn hello-world [] (println our-string))
This is a bit more complex. Like `def`, it uses a macro (`defn`) to create a variable - although this time, that variable is a function. The empty vector (a vector is a type of list -- think of it like an array) after `hello-world` defines the arguments to that function -- in this case, we don't have any. The code after that is what the function does. It evaluates `our-string`, which is equal to `"Hello world!"`, and prints it to the console. Let's run it!
(hello-world)
; => Hello world!
; nil
You could also write this:
(def hello-world (fn [] (println our-string)))
`defn` is just a shortcut to help keep your code concise. `(defn ...)` and `(def ... (fn ...))` are the same in practice.
## Parameters
Well, that was nice, but it wasn't really exciting. Let's try a function with parameters. How about one that adds 3 numbers?
(defn add [x y z] (+ x y z))
(add 1 2 3)
; => 6
...Hold on. `(+ x y z)`? That looks funny. Well, Lisps are written using "prefix notation", which means that the function always comes first. Since all mathematical operators in Lisp (`+ - * /`) are just functions, they also come before their arguments (in this case, `x y z`).
You'll notice that our vector has some stuff in it now: `[x y z]`! Whenever a function has parameters, you define them in that vector next to the function's name.
### Destructuring
A great feature about arguments in Clojure is destructuring. It allows you to 'pull' elements out of a list.
(defn add [[x y] z] (+ x y z))
(add [1 2] 3)
; => 6
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/SWlvKn' target='_blank' rel='nofollow'>IDEOne it!</a>
The arguments to that function are a collection (`[x y]`) and a number (`z`). We can use destructuring to pull the first and second elements out of the list, and call them `x` and `y`.
### Functions with any number of parameters
You can also define a function with an arbitrary number of arguments using `&`.
(defn demonstrate-rest [first & rest]
(println first)
(println rest))
(demonstrate-rest 1 "foo" ["bar" 22])
; => 1
; ("foo" ["bar" 22])
; nil
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/VftymP' target='_blank' rel='nofollow'>IDEOne it!</a>
As you can see, using `&` separated our function's arguments into one variable called `first` and a list of variables called `rest`. This means that our function could have any number of arguments!
## Returning
You may have noticed some odd things. Whenever we use `println`, it seems like `nil` is showing up in our output. Furthermore, our `add` function returns `6`, but we never told it to return anything.
In Clojure, returns are 'implicit'. If you've used Ruby, you're probably familiar with this concept. Rather than telling our function to return something, it evaluates all the code inside its body, and returns the result. Our `add` function, for example, evaluates `(+ x y z)`, and then returns that result.
The reason why our functions that use `println` output `nil` is because `println` evaluates to `nil`. (`nil` is like `null` or `None` -- it represents nothing.)
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ":point_left:") Previous](//forum.freecodecamp.com/t/what-is-clojure/18419) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:") Home ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [Next ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ":point_right:")](//forum.freecodecamp.com/t/clojure-conditionals/18412)|
| [Summary](//forum.freecodecamp.com/t/what-is-clojure/18419) | [Table of Contents](//forum.freecodecamp.com/t/clojure-resources/18422) | [Conditionals](//forum.freecodecamp.com/t/clojure-conditionals/18412)|

View File

@ -0,0 +1,95 @@
---
title: Clojure Lists They Are Everything
---
Lists are fundamental to Clojure. Clojure is a Lisp, and Lisps were originally used for list processing. Everything in a Lisp is a list!
(def foo "bar")
That piece of code is actually a list! So is anything between two round brackets in Clojure. Interesting, isn't it? This is what makes Lisps so interesting - you can easily write code that generates new code, because generating code is as simple as making a list.
## Making an actual list
The problem is, since everything is a list in Clojure, something like this will return an error:
(1 2 3 4 5)
; => ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn
What a horrid error message. What the REPL is trying to tell us is, "1 is not a function, and it can't be made into one." Because everything in a Lisp is a list, the first item of any list is treated as a function, like `def`, `+` or `str`, so if we write `(1 2 3 4 5)`, it treats the first element (`1`) as a function, which it clearly isn't.
We can solve this in two ways. One is using the `list` function to construct a list, like using `str` to concatenate strings together.
(list 1 2 3 4 5)
; => (1 2 3 4 5)
You can also use quoting. Quoting a list essentially says to the compiler that that list is _not_ a function call, and it shouldn't evaluate any of the code inside it.
'(1 2 3 4 5)
; => (1 2 3 4 5)
Interestingly, you can also quote function calls. This is how macros work. They're pretty complex, and deserve their own article, so we won't elaborate here.
;; Without a ' to quote it, this would return "foobarbaz".
'(str "foo" "bar" "baz")
; => (str "foo" "bar" "baz")
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/6c7UxY' target='_blank' rel='nofollow'>IDEOne it!</a>
## Adding to a list
Lists are designed for prepending, rather than appending. There is no real way to append to a list. You can prepend to a list using `cons`. `conj` also works, but that's meant for vectors, and `cons` is faster for lists.
(cons 1 '(2 3 4))
; => (1 2 3 4)
## Retrieving from lists
You retrieve items from lists using `nth`. `get` does not work on lists, because lists are designed for sequential access, rather than random access. Note that `nth` works on vectors, but is slower than `get` because of this.
(nth '(1 2 3 4) 0)
; => 1
## Converting other collections into lists
The `list` function can't convert other collections into lists, because it tries to construct a list using the arguments it's given. Passing `list` a collection will return a list containing that collection.
(list [1 2 3 4 5])
; => ([1 2 3 4 5])
To convert to a list, use the `seq` function instead.
(seq [1 2 3 4 5])
; => (1 2 3 4 5)
## Lazy sequences
Clojure has a brilliant feature called 'lazy sequences'. A lazy sequence is a list whose elements aren't generated until you refer to an element of the sequence later, at which point, it evaluates all the elements of the sequence up until the one you want. This allows you to construct "infinite" sequences!
`range` is perhaps the most simple lazy sequence. It contains all numbers.
(range 10)
; => (0 1 2 3 4 5 6 7 8 9)
(range -5 5)
; => (-5 -4 -3 -2 -1 0 1 2 3 4)
You can use lazy sequences to do really cool things, like generating a lazy sequence of all fibonacci numbers.
(def fibs
(lazy-cat [0 1] (map + (rest fibs) fibs)))
(take 10 fibs) ;; this means, "evaluate the first 10 fibonacci numbers."
; => (0 1 1 2 3 5 8 13 21 34)
This example is a bit advanced, and you shouldn't be expected to understand it if you're a beginner. It's just an example of something cool you can do with lazy sequences. Perhaps you can figure it out anyway!
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/jwpvt8' target='_blank' rel='nofollow'>IDEOne it!</a>
## When to use a list?
Using a vector is usually preferable to using a list, since there's no risk of the compiler accidentally evaluating a vector as a function, and it's faster to access arbitrary elements of a vector. Lists are most useful in 3 cases:
* Generating code using a macro.
* Generating "infinite" lazy sequences.
* Prepending elements to a collection.
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ":point_left:") Previous](//forum.freecodecamp.com/t/clojure-collections/18411) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:") Home ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [Next ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ":point_right:")](//forum.freecodecamp.com/t/clojure-vectors/18421)|
| [Collections](//forum.freecodecamp.com/t/clojure-collections/18411) | [Table of Contents](//forum.freecodecamp.com/t/clojure-resources/18422) | [Vectors](//forum.freecodecamp.com/t/clojure-vectors/18421)|

View File

@ -0,0 +1,89 @@
---
title: Clojure Looprecur
---
You may need to understand [`if`](//forum.freecodecamp.com/t/clojure-conditionals/18412) and [`let`](//forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415) to fully grasp recursion in Clojure.
## `for` and `while`
Clojure does not have for loops or while loops. This makes sense, if you think about it. A `for` loop changes a variable, and that's not allowed in Clojure.
for (var i = 0; i < 10; i++) {
console.log(i);
}
`i++` means that we add one to the variable `i` every time the loop finishes -- a clear example of a variable being mutated.
`while` loops are less obviously reliant on changing variables, but they are, just as much as for loops are.
var i = 0;
while (i < 10) {
console.log(i);
i++;
}
`while` loops always have a condition, like `i < 10`, and will break if that condition is no longer true. This means that they have to have some kind of side effect (like adding 1 to `i`) so that the condition will eventually be false; otherwise, the loop would last forever.
## Recursion
Thankfully, Clojure does have one loops of some kind. These loops use recursion -- a function that calls itself. The simplest recursive algorithm is one to find a positive number factorial (5 factorial, for example, equals `5 * 4 * 3 * 2`).
(defn fact [x]
(loop [n x prod 1] ;; this works just like a 'let' binding.
(if (= 1 n) ;; this is the base case.
prod
(recur (dec n) (* prod n)))))
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/3iP3tI' target='_blank' rel='nofollow'>IDEOne it!</a>
You'll notice that `(loop [n x prod 1] ...)` looks quite similar to a `let` binding. It actually works in just the same way -- here, we bind `n` to `x`, and `prod` to 1.
Every recursive function has a "base case". This is the condition that makes the loop stop looping. In this case, our loop stops if `n = 1`, and returns `prod`. If `n` isn't equal to 1, then the loop recurs.
(recur (dec n) (* prod n))
This `recur` function restarts the loop, but with different bindings. This time, `n` isn't bound to `x`, but is instead bound to `(dec n)` (which means `decrement n`, or `n - 1`), and `prod` is bound to `(* prod n)`.
So when we call the function, this is what happens:
(fact 5)
; Loop 1: 5 != 1, so the loop recurs with 4 (5 - 1) and 5 (1 * 5).
; Loop 2: 4 != 1, so the loop recurs with 3 (4 - 1) and 20 (5 * 4).
; Loop 3: 3 != 1, so the loop recurs with 2 (3 - 1) and 60 (20 * 3).
; Loop 4: 2 != 1, so the loop recurs with 1 (2 - 1) and 120 (60 * 2).
; Loop 5: 1 == 1, so the function returns prod, which is now equal to 120.
; => 120
The ingenious thing about recursion is that the variables themselves are never changed. The only thing that changes is what `n` and `prod` _refer to_. We never say, `n--`, or `n += 2`.
## Why use loop/recur?
You might be wondering why you would use `loop/recur` rather than simply defining a function that calls itself. Our factorial function could have been written like this:
(defn fact-no-loop [n]
(if (= 1 n)
1
(* n (fact-no-loop (dec n)))))
This is more concise, and works in a similar way. Why would you _ever_ use loop and recur?
### Tail Call Optimisation
If you use `loop/recur`, then the compiler (the software that turns Clojure code into JVM bytecode) knows that you want to create a recursive loop. This means that it tries its hardest to optimise your code for recursion. Let's compare the speed of `fact` and `fact-no-loop`:
(time (fact 20))
; => "Elapsed time: 0.083927 msecs"
; 2432902008176640000
(time (fact-no-loop 20))
; => "Elapsed time: 0.064937 msecs"
; 2432902008176640000
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/tpC0Xo' target='_blank' rel='nofollow'>IDEOne it!</a>
At this scale, the difference is negligible. In fact, `fact-no-loop` is occasionally faster than `fact` due to the unpredictable nature of computer memory. However, on a larger scale, this kind of optimisation can make your code much, much quicker.
### Nesting Recursion Within functions
`fact-no-loop` works without `loop/recur` because the entire function is recursive. What if we wanted part of our function to use a recursive loop, and then the rest of it to do something non-recursive? We'd have to define two entirely separate functions. Using `loop/recur` lets us use a little anonymous function instead.
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ":point_left:") Previous](//forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:") Home ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:")](//forum.freecodecamp.com/t/clojure-resources/18422) | Next ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ":point_right:")|
| [Let Bindings](//forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415) | [Table of Contents](//forum.freecodecamp.com/t/clojure-resources/18422) | To Be Added |

View File

@ -0,0 +1,71 @@
---
title: Clojure More on Functions
---
Functions! They're pretty important. It's very difficult to do anything without a function. They're integral to any language, but especially Clojure, since it's a functional programming language that rejects object-oriented design. Let's learn some more about them!
## Arity
**Arity** refers to the number of arguments that your function expects.
;; add expects 2 arguments. Its arity is 2.
(defn add [x y] (+ x y))
(add 2 2)
; => 4
;; + itself is a function, and it can have any number of arguments.
(+ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16) ;; and so on...
; => 136
Clojure has some special syntax that allows you to let your function do different stuff depending on the number of arguments it receives. This is called variable arity.
(defn foo
([] ; if this function gets no arguments...
(println "Lisa needs braces!")) ; do this.
([arg1] ; if this function gets 1 argument...
(println "Dental plan!"))) ; do this instead!
(foo)
; => Lisa needs braces!
; nil
(foo "this is a placeholder argument.")
; => Dental plan!
; nil
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/sXGplb' target='_blank' rel='nofollow'>IDEOne it!</a>
## Anonymous functions
Let's look at a really simple function: a function that adds 1 to a number.
;; I've called this function "my-inc" so you don't confuse it with inc.
;; inc is a built-in function that already does this for us.
(defn my-inc [n] (+ 1 n))
(inc' 5)
; => 6
This looks pretty simple. It takes a single parameter - `n` - and returns `n + 1`. Let's pick it apart.
(def my-inc-2 (fn [n] (+ 1 n)))
(inc' 5)
; => 6
You can see from this that using `defn` is just shorthand for using `(def ... (fn ...))`. But this reveals something interesting. What we're actually doing isn't 'defining a function', it's just binding an anonymous function to a special name - `inc'`. What if we don't give it a name?
((fn [n] (+ 1 n)) 5)
; => 6
Bam! Boom! Kapow! Anonymous functions. This might seem useless now, but it comes in pretty handy later on for applying functions to lists using `map`, `reduce` and `filter`. Giving every function you write a name gets boring and cumbersome, fast.
There's a shorter way to write anonymous functions, intended for very short, simple functions. It does not allow for destructuring or variable arity. However, it is quite concise.
(#(+ 1 %) 5)
; => 6
`#(...)` is a shorthand way to define an anonymous function. `%` refers to the first argument to the function. If your function expects several arguments, you can use `%1, %2, ... %n`.
(#(str %1 %2 %3) "foo" "bar" "baz")
; => "foobarbaz"
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/roYRgS' target='_blank' rel='nofollow'>IDEOne it!</a>
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ":point_left:") Previous](//forum.freecodecamp.com/t/clojure-loop-recur/18418) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:") Home ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [Next ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ":point_right:")](//forum.freecodecamp.com/t/clojure-collections/18411)|
| [Loop and Recur](//forum.freecodecamp.com/t/clojure-loop-recur/18418) | [Table of Contents](//forum.freecodecamp.com/t/clojure-resources/18422) | <a href='/http://forum.freecodecamp.com/t/clojure-collections/18411' target='_blank' rel='nofollow'>Collections</a>|

View File

@ -0,0 +1,18 @@
---
title: Clojure Resources
---
![Clojure Logo](//discourse-user-assets.s3.amazonaws.com/original/2X/3/3f3afa51f5d2c790faed68bfdd695d9f280e4480.png)
[Clojure](https://clojure.org/) is a dialect of Lisp with a focus on functional programming. It was released in 2007 by Rich Hickey, and has since gained a lot of popularity among web developers.
To learn about some of the language's core functions, you can consult the [documentation](https://clojuredocs.org/).
You could also consult any of these articles:
* [Summary - Why use Clojure?](http://forum.freecodecamp.com/t/what-is-clojure/18419)
* [Basics - Defining some variables and functions](http://forum.freecodecamp.com/t/clojure-the-basics/18410)
* [Conditionals - Using logic to add complex control flow to your programs](http://forum.freecodecamp.com/t/clojure-conditionals/18412)
* [Let bindings - Using local variables](http://forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415)
* [Loop and Recur - Using recursion to create loops in Clojure](http://forum.freecodecamp.com/t/clojure-loop-recur/18418)
For a brief and simple learning experience free online book [Clojure for the Brave and True](https://www.braveclojure.com/foreword/) can be used.

View File

@ -0,0 +1,85 @@
---
title: Clojure the Basics
---
### Getting Started
Before we begin, you may want to <a href='http://clojure.org/guides/getting_started' target='_blank' rel='nofollow'>install Clojure</a> and <a href='http://leiningen.org/#install' target='_blank' rel='nofollow'>Leiningen</a> (which is a tool for managing projects in Clojure). This will let you run Clojure in the command line using a REPL (Read-Evaluate-Print-Loop).
## Defining Variables
The bread and butter of any programming language are variables and functions. Let's define a variable!
(def our-string "Hello world!")
Easy peasy. That piece of code uses the `def` macro to associate a string (`"Hello world!"`) to a symbol (`our-string`). We could also have defined a number, such as `1` or `1.1`, a character, such as `\a` or `\Z`, or something more complicated like a list or a regular expression (_uuuugh_).
Note that our code is inside parentheses, like a list, because everything in a Lisp is a list! (That will be very important when we start talking about macros.)
## Defining Functions
Now, let's define a function!
(defn hello-world [] (println our-string))
This is a bit more complex. Like `def`, it uses a macro (`defn`) to create a variable - although this time, that variable is a function. The empty vector (a vector is a type of list -- think of it like an array) after `hello-world` defines the arguments to that function -- in this case, we don't have any. The code after that is what the function does. It evaluates `our-string`, which is equal to `"Hello world!"`, and prints it to the console. Let's run it!
(hello-world)
; => Hello world!
; nil
You could also write this:
(def hello-world (fn [] (println our-string)))
`defn` is just a shortcut to help keep your code concise. `(defn ...)` and `(def ... (fn ...))` are the same in practice.
## Parameters
Well, that was nice, but it wasn't really exciting. Let's try a function with parameters. How about one that adds 3 numbers?
(defn add [x y z] (+ x y z))
(add 1 2 3)
; => 6
...Hold on. `(+ x y z)`? That looks funny. Well, Lisps are written using "prefix notation", which means that the function always comes first. Since all mathematical operators in Lisp (`+ - * /`) are just functions, they also come before their arguments (in this case, `x y z`).
You'll notice that our vector has some stuff in it now: `[x y z]`! Whenever a function has parameters, you define them in that vector next to the function's name.
### Destructuring
A great feature about arguments in Clojure is destructuring. It allows you to 'pull' elements out of a list.
(defn add [[x y] z] (+ x y z))
(add [1 2] 3)
; => 6
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/SWlvKn' target='_blank' rel='nofollow'>IDEOne it!</a>
The arguments to that function are a collection (`[x y]`) and a number (`z`). We can use destructuring to pull the first and second elements out of the list, and call them `x` and `y`.
### Functions with any number of parameters
You can also define a function with an arbitrary number of arguments using `&`.
(defn demonstrate-rest [first & rest]
(println first)
(println rest))
(demonstrate-rest 1 "foo" ["bar" 22])
; => 1
; ("foo" ["bar" 22])
; nil
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/VftymP' target='_blank' rel='nofollow'>IDEOne it!</a>
As you can see, using `&` separated our function's arguments into one variable called `first` and a list of variables called `rest`. This means that our function could have any number of arguments!
## Returning
You may have noticed some odd things. Whenever we use `println`, it seems like `nil` is showing up in our output. Furthermore, our `add` function returns `6`, but we never told it to return anything.
In Clojure, returns are 'implicit'. If you've used Ruby, you're probably familiar with this concept. Rather than telling our function to return something, it evaluates all the code inside its body, and returns the result. Our `add` function, for example, evaluates `(+ x y z)`, and then returns that result.
The reason why our functions that use `println` output `nil` is because `println` evaluates to `nil`. (`nil` is like `null` or `None` -- it represents nothing.)
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ":point_left:") Previous](//forum.freecodecamp.com/t/what-is-clojure/18419) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:") Home ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [Next ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ":point_right:")](//forum.freecodecamp.com/t/clojure-conditionals/18412)|
| [Summary](//forum.freecodecamp.com/t/what-is-clojure/18419) | [Table of Contents](//forum.freecodecamp.com/t/clojure-resources/18422) | [Conditionals](//forum.freecodecamp.com/t/clojure-conditionals/18412)|

View File

@ -0,0 +1,63 @@
---
title: Clojure Vectors
---
A vector is perhaps the most simple type of collection in Clojure. You can think of it like an array in Javascript. Let's define a simple vector:
(def a-vector [1 2 3 4 5])
;; Alternatively, use the vector function:
(def another-vector (vector 1 2 3 4 5))
;; You can use commas to separate items, since Clojure treats them as whitespace.
(def comma-vector [1, 2, 3, 4, 5])
You'll see that it uses square brackets, just like an array in JS. Since Clojure, like JS, is dynamically typed, vectors can hold elements of any type, including other vectors.
(def mixed-type-vector [1 "foo" :bar ["spam" 22] #"^baz$"])
## Adding items to a vector
You can append items to a vector using `conj`. You can also prepend to a list using `into`, but note that `into` is intended for merging two vectors, so both its arguments must be vectors, and using `into` is slower than using `conj`.
(time (conj [1 2] 3))
; => "Elapsed time: 0.032206 msecs"
; [1 2 3]
(time (into [1] [2 3]))
; => "Elapsed time: 0.078499 msecs"
; [1 2 3]
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":rocket:") <a href='https://ideone.com/wBSUEd' target='_blank' rel='nofollow'>IDEOne it!</a>
## Retrieving items from a vector
You can retrieve items from a vector using `get`. This is equivalent to using bracket notation to access items in an array in many imperative languages. Items in a vector are 0-indexed, counting from the left.
var arr = [1, 2, 3, 4, 5];
arr[0];
// => 1
In Clojure, this would be written like so:
(def a-vector [1 2 3 4 5])
(get a-vector 0)
; => 1
You can also give `get` a default value, if you give it an index that isn't in the array.
;; the list doesn't have 2147483647 elements, so it'll return a string instead.
(get a-vector 2147483646 "sorry, not found!")
; => "sorry, not found!"
## Converting other collections into vectors
Non-vector data structures can be converted into vectors using the `vec` function. With hashmaps, this produces a 2D vector containing pairs of keys and values.
(vec '(1 2 3 4 5))
; => [1 2 3 4 5]
(vec {:jack "black" :barry "white"})
; => [[:jack "black"] [:barry "white"]]
## When to use a vector?
A vector should be used in almost all cases if you need a collection, because they have the shortest random-access times, which makes it easy to retrieve items from a vector. Note that vectors are ordered. If order doesn't matter, it may be better to use a set. Also note that vectors are designed for appending items; if you need to prepend items, you might want to use a list.
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ":point_left:") Previous](//forum.freecodecamp.com/t/clojure-lists-they-are-everything/18417) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:") Home ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":book:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [Next ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ":point_right:")](//forum.freecodecamp.com/t/clojure-hashmaps/18414)|
| [Lists](//forum.freecodecamp.com/t/clojure-lists-they-are-everything/18417) | [Table of Contents](//forum.freecodecamp.com/t/clojure-resources/18422) | [Hashmaps](//forum.freecodecamp.com/t/clojure-hashmaps/18414)|