Maths

Fixme Split this into sections ?

Writing some simple mathematics helps you get used to the form of Clojure. Unlike other languages, Clojure does not have operators for mathematics. Instead + - * / are all functions in their own right.

As Clojure uses pre-fix notation then mathematical expressions are always unambiguous. There is no need for an operator precedence table in Clojure.

Note Write some simple math to help you get used to the form of Clojure

  1. (+ 1 2 3 4 5 6 7)
  2. (- 2 1)
  3. (* 3 7)
  4. (/ 12 4)
  5. (/ 500 20)
  6. (+ 1 1 2489 459 2.)
  7. (+ 1 2 (* 3 4) (- 5 6 -7))

Numbers & Maths - 图1

Variable numbers of arguments

Mathematic functions show the flexibility of Clojure, as they take a variable number of arguments (variadic functions). Its common for Clojure functions to have zero, one or many arguments (many arguments typically represented as a built-in data structure (map, vector, set or list)

Note Write some more maths to show the variadic nature of mathematic (and manu other) functions

  1. (+)
  2. (*)
  3. (* 2)
  4. (+ 4)
  5. (+ 1 2 3)
  6. (< 1 2 3)
  7. (< 1 3 8 4)

Numbers & Maths - 图2

Note Explore some number related functions

  1. (rem 22 7)
  2. (mod 20 12)
  3. (quot 13 4)
  4. (inc 3)
  5. (dec 4)
  6. (min 1 2 3 5 8 13)
  7. (max 1 2 3 5 8 13)
  8. (repeat 4 9)
  9. (range 10)
  10. (range 18 66)
  11. (range 2 99 2)

Equality

Equality is represented by the = function. Yes, = is a proper function too, not just an operator as with other languages.

Note Explore what equality means in Clojure. Equality is very useful when your data structures are immutable

  1. (= 1 1)
  2. (= 2 1)
  3. (identical? "foo" "bar")
  4. (identical? "foo" "foo")
  5. (= "foo" "bar")
  6. (= "foo" "foo")
  7. (identical? :foo :bar)
  8. (identical? :foo :foo)
  9. (true)
  10. (false)
  11. (not true)
  12. (true? (= 1 1))
  13. (false (= 1 -1))

Equality is very efficient when your data structures are immutable. For example if you have very large data sets, you can simply compare a hash value to see if those data structures are the same.

Of course you also have the not function for reversing logic too

  1. (not true)
  2. => false

Truethy experiments

;; some truthiness with math functions for you to try

  1. (+)
  2. (class (+))
  3. (*)
  4. (true? +)
  5. (false? +)
  6. (true? *)
  7. (false? *)
  8. (true? 1)
  9. (true? -1)
  10. (true? true)
  11. (- 2)

Boolean & Predicates

Predicates are functions that take a value and return a boolean result (true | false)

  1. (true? true)
  2. (true? (not true))
  3. (true? false)
  4. (true? (not false))
  5. (true? nil)

Types

Clojure uses Java’s object types for booleans, strings and numbers. Use the class function to inspect them.

  1. (class 1)
  2. ; Integer literals are java.lang.Long by default
  3. (class 1.1) ; Float literals are java.lang.Double
  4. (class "")
  5. ; Strings always double-quoted, and are java.lang.String
  6. (class false) ; Booleans are java.lang.Boolean
  7. (class nil) ; The "null" value is called nil
  8. (class (list 1 2 3 4))
  9. (class true)
  10. (class ())
  11. (class (list 1 2 34 5))
  12. (class (str 2 3 4 5))
  13. (class (+ 22/7))
  14. (class 5)
  15. (class "fish")
  16. (type [1 2 3])
  17. (type {:a 1 :b 2})
  18. (type (take 3 (range 10)))

Ratios

To help maintain the precision of numbers, Clojure has a type called Ratio. So when you are dividing numbers you can keep the as a fraction using whole numbers, rather than constrain the result to a approximate

  1. (/ 2)

A classic example is dividing 22 by 7 which is approximately the value of Pi

  1. (/ 22 7)
  2. (class (/ 22 7))

If you want to force Clojure to evaluate this then you can specify one of the numbers with a decimal point

  1. (class (/ 22 7.0))