Mercurial > repos > other > SevenLanguagesInSevenWeeks
comparison 6-Clojure/README.txt @ 81:0f57e5c2ae82
Add notes on sequences in Clojure
Next up: infinite sequences!
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Thu, 06 Jun 2019 20:56:16 +0100 |
parents | a83309cdf5d3 |
children | cf7182bca068 |
comparison
equal
deleted
inserted
replaced
80:a83309cdf5d3 | 81:0f57e5c2ae82 |
---|---|
35 | 35 |
36 The "if" function is basically "if <condition> <true>[ <false>]". | 36 The "if" function is basically "if <condition> <true>[ <false>]". |
37 | 37 |
38 Note: 0 and "" are true but nil is false, so only false and the null value are falsey. | 38 Note: 0 and "" are true but nil is false, so only false and the null value are falsey. |
39 | 39 |
40 Clojure has four main data structures - lists (for code), vectors (for data), sets and maps. | 40 Clojure has four main data structures - lists (for code), vectors (for data), sets and maps. These are types of sequence. Other things may also be sequences (strings, file system structures, etc). |
41 Sequences can then be operated on with "first", "last", "rest" and "cons" (construct from head and tail) functions. | |
41 | 42 |
42 You can't build a list Python style with "(1 2 3)". You need either "(list 1 2 3)" or the odd syntax "'(1 2 3)". | 43 You can't build a list Python style with "(1 2 3)". You need either "(list 1 2 3)" or the odd syntax "'(1 2 3)". |
43 Lists can then be operated on with "first", "last", "rest" and "cons" (construct from head and tail) functions. | |
44 There are also functions like "nth" (nth <list> <0-based index>) | 44 There are also functions like "nth" (nth <list> <0-based index>) |
45 | 45 |
46 Vectors use sequare brackets. They're like a list, but you can implicitly index them (i.e. you don't need "nth") by doing ([vector] pos) because they're treated as functions. | 46 Vectors use sequare brackets. They're like a list, but you can implicitly index them (i.e. you don't need "nth") by doing ([vector] pos) because they're treated as functions. |
47 | 47 |
48 first, last and rest can be used for pattern matching. | 48 first, last and rest can be used for pattern matching. |
77 is equivalent to: | 77 is equivalent to: |
78 (map #(* 2 (count %)) my_list) | 78 (map #(* 2 (count %)) my_list) |
79 | 79 |
80 As well as the map function, there's "apply" and "filter". | 80 As well as the map function, there's "apply" and "filter". |
81 | 81 |
82 Also, some helper functions exist, like "odd?". | 82 Also, some helper functions exist, like "odd?". Terminating in a question mark seems to be the Clojure approach to predicates. Sometimes you end up with multiple question marks: |
83 | |
84 (every? number? [1 2 3 :four]) | |
85 ;false | |
86 | |
87 not-every? and not-any? both have question marks as well. But not everything is question marked: | |
88 | |
89 (some nil? [1 2 nil]) | |
90 ; true | |
91 | |
92 This seems oddly inconsistent. The footnote explains that it's because "some returns the first value that is not nil or false", so "nil?" return false for 1 and 2 and then return true for nil and so some returns it. | |
93 It's not a predicate because "(some nil? [1 2]) returns nil, not false. | |
83 | 94 |
84 Functional languages do lazy tail recursion. Unless they're Clojure, because the JVM doesn't support it. Clojure does it with a "loop" and a "recur" function. "loop" takes x and y with initial values and a function to call. See loop_recur.clj. | 95 Functional languages do lazy tail recursion. Unless they're Clojure, because the JVM doesn't support it. Clojure does it with a "loop" and a "recur" function. "loop" takes x and y with initial values and a function to call. See loop_recur.clj. |
85 | 96 |
97 For loops take the form (for [val collection<, val2 collection2<, …>>] (body)), which is a bit like "for X in Collection", but doesn't look like it at first. | |
98 Multiple val/collection pairs give nested for loops (so every val with every val2). | |
99 | |
100 But then for loops can take a ":when" test keyword (or :let or :while). Which is odd, because :xxx has only ever been a user atom, but this one already has meaning. And they can be mixed anywhere in the parameters and Clojure knows what to do. | |
101 | |
102 Reduce is more familiar: (reduce func list) | |
103 | |
104 (reduce + [1 2 3 4]) ; sums | |
105 (reduce * [1 2 3 4 5]) ; factorial | |
106 | |
107 As well as sorting a list with (sort list) you can use a custom funcion with (sort-by function list) where "function" takes a single parameter and generates a key. |