Transcript Clojure 2

Clojure 2
26-Jul-16
Running Clojure

C:\Users\Dave>cd C:\Programs\clojure-1.2.0
C:\Programs\clojure-1.2.0>java -cp clojure.jar clojure.main
Clojure 1.2.0
user=> (load-file "E:/Programming/Clojure programs on E/test.clj")
#'user/fruit
user=>


Although jEdit has a clojure mode, I don’t like it



The response, #'user/fruit, is because “fruit” was the last thing defined on this file
Syntax coloring is good, but indentation is strange (buggy?) and agressive
The lisp mode doesn’t syntax color as well, but indents properly
Comments:


A “doc” string is a string that goes just before the parameter list
Other comments start with a semicolon (;) and extend to the end of the line
Functions

The syntax to define a named function is:
(defn function_name [arguments] expressions)


The value of the function is the value of the last expression
evaluated
The syntax of a function call is
(function arguments)


Notice that the function being called is the first thing inside
the parentheses
This need not be the name of a function; it can be any
expression that results in a function
4
Tail recursion (Erlang)

Non-tail recursive function to find the length of a list:
len([]) -> 0;
len([_ | T]) -> 1 + len(T).

Tail recursive function to find the length of a list:
len(L) -> len(0, L).
len(N, []) -> N;
len(N, [_ | T]) -> len(N + 1, T).
Tail recursion (Clojure)

Non-tail recursive function to find the length of a list:
(defn len-1 [lst]
(if (empty? lst)
0
(inc (len-1 (rest lst))) ) )

Tail recursive function to find the length of a list:
(defn len-2
([lst] (len-2 0 lst))
([n lst]
(if (empty? lst)
n
(len-2 (inc n) (rest lst))) ) )
recur



The previous function, len-2, is tail-recursive, but the
compiler doesn’t optimize it into a loop
Clojure runs on the JVM, which doesn’t optimize tail
recursion
Workaround:
(defn len-2
([lst] (len-2 0 lst))
([n lst]
(if (empty? lst)
n
(recur (inc n) (rest lst))) ) )
Tail recursion (Erlang)

Non-tail recursive function to find the factorial:
factorial(1) -> 1;
factorial(N) -> N * factorial(N - 1).

Tail recursive function to find the factorial:
factorial(N) -> factorial(1, N).
factorial(Acc, 1) -> Acc;
factorial(Acc, N) -> factorial(N * Acc, N - 1).
Tail recursion (Clojure)

Non-tail recursive function to find the factorial:
(defn factorial-1 [n]
(if (= n 1)
1
(* n (factorial-1 (dec n))) )

Tail recursive function to find the factorial:
(defn factorial-2
([n]
(factorial-2 1 n))
([acc n]
(if (= n 1)
acc
(recur (* n acc) (dec n)) ) ) )
map




(def fruit '((apple red) (banana yellow) (cherry red)))
user=> (map first fruit)
(apple banana cherry)
(defn my-map [f lst]
(if (empty? lst)
()
(cons (f (first lst)) (my-map f (rest lst))) ) )
user=> (map my-first fruit)
(apple banana cherry)
Anonymous functions

An anonymous function has the syntax:
(fn [parameters] body)

Example:
(fn [x] (* x x))
filter




(def fruit '((apple red) (banana yellow) (cherry red)))
user=> (filter (fn [x] (= (second x) 'red)) fruit)
((apple red) (cherry red))
(defn my-filter [p lst]
(cond
(empty? lst) ()
(p (first lst)) (cons (first lst) (my-filter p (rest lst)))
:else (my-filter p (rest lst)) ) )
user=> (my-filter (fn [x] (= (second x) 'red)) fruit)
((apple red) (cherry red))
Speaking of maps…

A map or hash is a sequence of key/value pairs, enclosed in
braces, for example,
{:ace 1, :deuce 2, "trey" 3}



A map is also a function:



Elements are separated by whitespace or commas
It is helpful to use commas between key/value pairs
user=> (def cards {:ace 1, :deuce 2, "trey" 3})
#'user/cards
user=> (cards :deuce)
2
Keywords are also functions:

user=> (:deuce cards)
2
structs

A struct is something like a Java class

(defstruct book :title :author)
(def b (struct book "Small Gods" "Terry Pratchett"))

A struct is something like a map

(:author b) returns "Terry Pratchett"
