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.