Introduction to ClojureScript


J David Eisenberg <david.eisenberg@evc.edu>
Evergreen Valley College


Hit the space bar or swipe left for next slide

ClojureScript

What’s a function?

Functions inside functions

How to Write ClojureScript

Everything is a list.

A list consists of:

Example:

(+ 3 5)

You may edit the code to try other numbers and operators. Press CTRL-ENTER to evaluate the code.

More Arithmetic

Here are your arithmetic functions:

+, -, *, /, quot, and rem

()

All of these except the last two take multiple arguments. The last two are for integer division and remainder.

Multiple Arithmetic Operations

Translate 3 + 4 * 5 to ClojureScript:

(+ 3 (* 4 5))

How about 3 * 4 + 5?

()

How Algebraic Variables Work

angry cat saying 'U NO CAN DO THAT!'

Photo Credit: Angela P

x = 5

y = x · 3

How Algebraic Variables Work (cont.)

angry cat saying 'U NO CAN DO THAT!'

Photo Credit: Angela P

x = 5

y = x · 3

x = 6 International prohibition symbol

Symbols in ClojureScript

Here is the model:

(def symbol value)
(def x 27)

In ClojureScript, you bind a symbol to a value.

In other languages, variables do not work as in algebra. Instead of binding a symbol to a value, a variable refers to a location in memory that can be updated at any time.

Defining Functions

The model:

(def symbol (fn [parameters]
             function-body))

Some Concrete Examples


(def average (fn [a b] (/ (+ a b) 2.0)))
(def cube (fn [n] (* n n n)))

Interacting with JavaScript

What if I wanted to do the Pythagorean distance formula? I would need to do a square root...

(sqrt (+ (* 3 3) (* 4 4)))

Interacting with JavaScript (cont.)

What if I wanted to do the Pythagorean distance formula? I would need to do a square root...

(sqrt (+ (* 3 3) (* 4 4)))
Confused cat with caption: Y that no work?
Photo Credit: Alan Turkus

How to Access JavaScript

TaskClojureScriptExample
Call a method (.method js/object argument ...) (.max js/Math 3 5 7 2)
Get a property’s value (.-property js/object) (.-title js/document)
Create a new object (js/object.) (js/Date.)
Set a property’s value (set! (.-property js/object) value) (set! (.-title js/document) "New Title")

Try these!

()

Some Shortcuts

Defining a function

(def square (fn [x] (* x x))) ⇒ (defn square [x] (* x x))

Accessing JavaScript methods

(.sqrt js/Math 5) ⇒ (js/Math.sqrt 5)

(.parseFloat js/window "12.3") ⇒
   (js/window.parseFloat "12.3") ⇒
   (js/parseFloat "12.3")
()

Pythagorean Distance


(def distance (fn [a b]
                (js/Math.sqrt (+ (* a a) (* b b)))))

The HTML

<p>
a = <input type="text" id="a" size="5"/>
b = <input type="text" id="b" size="5"/>
c = <span id="c"></span>
</p>

<p>
<input type="button" value="Calculate" id="calculate"/>
</p>

Which looks like this...

a = b = c =

Off to the “real world”...

Let’s go to a real development environment to complete this example.

Loose Ends

Local Variables

Here is the formula for monthly payment on a loan:

We want a function that takes:

It would be convenient to have temporary variables for:

Local Variables with let


(defn payment [principal apr years]
  (let [rate (/ (/ apr 100) 12) ; convert to monthly decimal
        n (* years 12) ; convert to months
        sub-formula (js/Math.pow (+ 1 rate) n)]
    (* principal (/ (* rate sub-formula) (- sub-formula 1)))))
    
(payment 5000 7.25 10)

Conditionals with if

The model:

(if condition true-expr false-expr)

Conditional functions: =, not=, <, >, <=, >=

Conditional operator functions: and, or, not

(defn tester [condition]
  (if condition "yes" "no"))
  
(tester (< 3 5))

Series of Conditions with cond


(defn test-cond [qty]
  (let [price 3.95
        subtotal (* price qty)]
  (cond
    (< qty 10) subtotal
    (< qty 20) (* subtotal .90)
    (< qty 50) (* subtotal .85)
    :else (* subtotal .75))))

(test-cond 10)

Collections

Lists

(list 1 2 (- 8 5))

List Operations

(def data (list 10 11 12 13 14))
(first data)

Vectors

[1 2 (- 8 5)]

Vector Operations

(def data [10 11 12 13 14])
(first data)

Iterating through a List/Vector

Consider this code to calculate a 10% discount on a price:

(defn discount [price]
  (* price 0.90))

With this vector of prices:

(def price-vector [3.95 6.80 2.49 5.33 1.99])

The map function

The map function applies a function to each element of a list, generating a new sequence of values:

(defn discount [price]
  (* price 0.90))

(def price-vector [3.95 6.80 2.49 5.33 1.99])

(map discount price-vector)

map 1

map 2

map 3

map 4

map 5

map 6

Huh?!

(defn discount [price]
  (* price 0.90))

(def price-vector [3.95 6.80 2.49 5.33 1.99])(map discount price-vector)
alert cat saying 'WAT U DO THERE?'
Photo credit: furlined

List Comprehensions

(def price-vector [3.95 6.80 2.49 5.33 1.99])

(for [price price-vector]
  (* price 0.90))

Reducing a Collection to a Value

Given a vector of numbers:

[2 3 5]

How do I get the sum of the squares of the numbers?

The reduce function

(defn sumsq [result value]
  (+ result (* value value)))

(reduce sumsq 0 [2 3 5])

Calling reduce

The reduction function

(defn sumsq [result value]
  (+ result (* value value)))

accumulated result of reduction
individual value from collection

reduce 1

reduce 2

reduce 3

reduce 4

Back to the Real World

Develop a web page to calculate mean and standard deviation.

The map collection

Creating and using maps

(def capitals {:paris "France" :london "England" :washington-dc "USA"})

Further Links