0% found this document useful (0 votes)
14 views

Tutorial 09

Clojure is a Lisp-based programming language that runs on the Java Virtual Machine. It provides first-class functions and immutable persistent data structures. This document outlines how to set up a development environment for Clojure by installing Java, Leiningen, and optionally the Calva extension for Visual Studio Code. It then provides an introduction to Clojure concepts like defining anonymous functions, passing functions as arguments, storing functions in variables, using atoms for mutable state, and its basic data types like integers, floats, and hexadecimal values.

Uploaded by

arya hajari
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

Tutorial 09

Clojure is a Lisp-based programming language that runs on the Java Virtual Machine. It provides first-class functions and immutable persistent data structures. This document outlines how to set up a development environment for Clojure by installing Java, Leiningen, and optionally the Calva extension for Visual Studio Code. It then provides an introduction to Clojure concepts like defining anonymous functions, passing functions as arguments, storing functions in variables, using atoms for mutable state, and its basic data types like integers, floats, and hexadecimal values.

Uploaded by

arya hajari
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

COMP348

PRINCIPLES OF PROGRAMMING LANGUAGES

TUTORIAL 9
Clojure: Setup and Introduction

COMP 348 Principles of Programming Languages


Fall 2022
Setting up a development environment for Clojure
1. Install Java on Ubuntu

Check if java is already installed, any version >= 8 is fine, default recommended version is 11.
a. Run `java --version` and `javac --version` in ubuntu terminal. If the commands do not show any output,
proceed with the following steps.
b. Run `sudo apt update` in terminal to update the package lists.
c. Run `sudo apt install default-jre` to install the default java runtime.
d. Run `sudo apt install default-jdk` to install the default java development environment.
e. Run `java --version` and `javac --version` again to ensure java is installed, it should produce the following
output.

COMP 348 Principles of Programming Languages

2
Setting up a development environment for Clojure
2. Installing Leiningen
Leiningen is a tool for building clojure projects.
a. Run `sudo apt update` in ubuntu terminal to update the package lists.
b. Run `sudo apt install leiningen` to install leiningen package.
c. Run `lein new app hello-world` to create a hello-world project to test the installation. It should should display the following output.

d. Enter the newly created hello-world directory with `cd hello-world` and run `lein run`. For the first run of the project, clojure
dependencies will be downloaded. Ensure that the following output is displayed and the last line of the output displays
“Hello, World!”

COMP 348 Principles of Programming Languages 3


Setting up a development environment for Clojure
e. In the hello-world project directory, run `lein repl` in Ubuntu terminal. This starts a clojure REPL (similar to the python
interpreter) which loads up all dependencies and source code of the hello-world project. Following output should be displayed
(note that the port number for the server may be different.)

f. To ensure that the project source code has been loaded up into the clojure REPL, try running the main function as defined in
hello-world/src/hello_world/core.clj by typing `(-main)` in the REPL.

g. To exit the clojure REPL, type `quit` or `exit` or hit Ctrl+D.

COMP 348 Principles of Programming Languages

4
Setting up a development environment for Clojure
Optionally, an extension can be installed for Visual Studio Code. It provides features such as auto-
completion in clojure REPL, importing source code quickly into the REPL etc.

1. If WSL is being used, ensure Visual Studio Code is connected to Ubuntu WSL (lower left icon
should display “WSL:Ubuntu”, follow steps outlined in tutorial 0 for WSL-VS Code plugin)
2. Open Extensions and search for “Calva” and install the extension. For WSL, ensure that “Install in
WSL: Ubuntu” is selected from the drop down menu.

COMP 348 Principles of Programming Languages 5


Setting up a development environment for Clojure
3. Once the extension is installed, open the previously created hello-world project in VSCode and navigate to the
core.clj file under src/hello_world.
4. Open the VSCode command palette with the shortcut Shift+Command+P (Mac) or Ctrl+Shift+P
(Windows/Linux). Enter the command `jack in` and select `Calva: Start a Project REPL and
Connect`. Select ‘hello-world’ as the project and ‘leiningen’ as the project type, when prompted. Leave the profile
empty. This should start the REPL, the functions defined in the core.clj can be run in the REPL now.

6
COMP 348 Principles of Programming Languages
Hello World!
● In REPL, we start by defining the following function:
(fn [] "Hello World!")
● On evaluation, this produces the following output:
#function[...]

● What we have created is an anonymous or a ‘lambda’ function, we need to


evaluate it by surrounding it in matched parentheses as follows:
((fn [] "Hello World!"))
● This produces the expected output as follows:
“Hello World!”

COMP 348 Principles of Programming Languages

7
Function as a unit of computation

1. In line with LISP, in clojure, everything is a list.

(VERB PARAM1 PARAM2 …)

1. Everything has a return value (but there is no ‘return’ keyword). Everything


has a value that is returned at the end of operations. If nothing is specified,
‘nil’ will be returned.
2. As previously defined, (fn [] "Hello World!") creates a lambda function
that takes no parameters and returns “Hello World!”.
3. The function is ‘invoked’ by specifying it as the first element in the list ((fn []
"Hello World!")) and no argument is passed to this lambda function.
COMP 348 Principles of Programming Languages

8
First class functions
● Clojure has first class functions i.e. functions can be saved in labels, they can
be passed to other functions as arguments, and functions can return functions
as well.
● To store a lambda function in a label:
(def hello (fn [] "Hello World!"))
● To invoke it:
(hello) -> "Hello World!"
● In fact, a function passed as an argument to another function which has
access to the context of the receiving function’s state is called a closure, a
keypoint after which the language is named.
COMP 348 Principles of Programming Languages

9
Variables and atoms
● ‘def’ is used to bind a value to a variable label: (def a 5)
● The identifier follows similar rules to other programming languages, it can contain alphabets, numbers and
underscore, and it cannot begin with a number. The identifier is case sensitive.
● Note that bound variables are immutable, to be reassigned they have to be destroyed and recreated again.
● For modifiable state, clojure uses ‘atoms’, these atoms can be thought of as references to variables that
can be updated in a thread-safe manner.
(defn Atoms Output:
; Conditionally update the value if the
[]
expected value is found
(def amount (atom 100)) Amount: 100
(compare-and-set! amount 110 120) ; will
(println "Amount: " @amount) Incremented amount: 101
update the value, as amount was 110
Amount after resetting: 110
(println "Comparing with 110 and updating
; Exactly one thread can perform any of the Comparing with 110 and updating to 120,
to 120, amount: " @amount)
following updates amount: 120
; Apply a function on the atom to update its Comparing to 110 and updating to 150,
(compare-and-set! amount 110 150) ; will
value amount: 120
not update the value, as amount was 120
(swap! amount inc) nil
(println "Comparing to 110 and updating
(println "Incremented amount: " @amount)
to 150, amount: " @amount))

; Reset the value of the atom with the given


(Atoms)
value
(reset! amount 110) COMP 348 Principles of Programming Languages
(println "Amount after resetting: " @amount)
10
Data types
(defn DataTypes [] ; Evaluating file: data_types.clj
(def a 1) ; integer
1
(println a)
(def b 1.25) ; float 1.25
(println b) 1.25E-12
(def c 1.25e-12) ; float in scientific notation
64508
(println c)
(def d 0xfbfc) ; hex nil
(println d) true
(def e nil) ; null value Hello
(println e)
(def f true) ; true/false boolean thanks
(println f)
(def g "Hello") ; string ● Clojure supports atoms for mutating state and the
(println g) following default java data types (from java.lang: byte,
(def h 'thanks) ; keyword, a reference that can be used short, integer, long, float, double)
in multiple parts of the code ● In Clojure, only “nil” and “false” are considered false-y,
(println h)) everything else is considered truth-y. [ To quickly test the
false-y/truth-y value, use (if <expr> “true” “false”) ]
(DataTypes)

COMP 348 Principles of Programming Languages

11
Operators
● Clojure provides 4 standard types of operators: arithmetic, relational, logical
and bitwise.
; arithmetic ; relational ; logical operators ; bitwise operators
(+ 1 2) (= 2 2) ; true (and true false) ; false (bit-and 5 12) ; 0101 1100 -> 0100
(- 5 3) (not= 2 3) ; true (or true false) ; true (4)
(* 6 3) (< 2 3) ; true (not true) ; false (bit-or 5 12) ; 0101 1100 -> 1101
(/ 3 2) (<= 3 3) ; true (13)
(inc 5) (> 3 6) ; false (bit-xor 5 12) ; 0101 1100 -> 1001
(dec 5) (>= 2 3) ; false (9)
(max 3 6) (bit-not 5) ; 0101 -> 1010
(min 3 6)
(rem 5 3)

● Note that operator precedence isn’t inferred here, we explicitly specify the
order by creating lists that will be evaluated.
COMP 348 Principles of Programming Languages 12
Conditionals in clojure: if and if-do
● Basic construct: (defn conditionalIf (defn conditionalIfDo
[] []
(if boolean-form
(println "conditionalIf:") (println "\nconditionalIfDo:")
then-form
(if (and (= 5 5) (or (= 2 2) (if (= 5 6)
optional-else-form
(not true))) (do (println "Equal: first statement")
)
(println "True") (println "Equal: Second statement"))
● For eg:
(println "False"))) (do (println "Not equal: first statement")

(if (> 5 0) (conditionalIf) (println "Not equal: second statement"))))


"positive" (conditionalIfDo)
Output :
"negative"
Output :
) conditionalIf: conditionalIfDo:
"positive" True Not equal: first statement
Not equal: second statement
● What will the following line return?
(if (if (println "boo") "woo") "truth-y" "false-y")
● Output:
boo COMP 348 Principles of Programming Languages
"false-y"
13
Conditionals in clojure: case and cond
● Case ● Cond

(defn conditionalCase (defn condtionalCond


[] [amount]
(println "\nconditionalCase:") (println "\nconditionalCond:")
(def pet "dog") (cond
(case pet (<= amount 2) (println "amount <= 2")
"cat" (println "I have a cat") (<= amount 10) (println "amount <= 10")
"dog" (println "I have a dog") (<= amount 100) (println "amount <= 100")
"fish" (println "I have a fish"))) :else (println "amount > 100")))
(conditionalCase) (condtionalCond 75)

● Output: ● Output:
conditionalCase: conditionalCond:
I have a dog amount <= 100

COMP 348 Principles of Programming Languages

14
Introduction to functions
● A function in clojure follows the following format. The return value of the function is the value of the last expression.

; standard form of a function


(defn func_name
"doc string" ; standard documentation
[params]
(expression_1)
(expression_2)
...
(expression_n))

● Computing sum of a first n numbers recursively:

(defn sum
"Compute sum of numbers recursively"
Output:
[n]
(if (<= n 1) (sum 10) -> 55
n
(+ n (sum (- n 1)))))
COMP 348 Principles of Programming Languages

15
Introduction to functions
● Fibonacci numbers computed recursively. ● Factorial computed recursively.

(defn fib (defn fact


"Compute n'th fibonacci term recursively" "Compute factorial of a given number
[n] recursively"
(if (<= n 1) [n]
n (if (<= n 1)
(+ (fib (dec n)) (fib (- n 2))))) 1
● Output: (* n (fact (- n 1)))))
● Output:
(map fib (range 10))
(0 1 1 2 3 5 8 13 21 34) (map fact (range 10))
(1 1 2 6 24 120 720 5040 40320 362880)

What happens if we try to evaluate (fact 10000)?


(fact 10000) -> ; Execution error (StackOverflowError)
The stack blew up. We will fix this in the next session.
COMP 348 Principles of Programming Languages

16
References

1. https://clojure.org/guides/install_clojure
2. https://leiningen.org/#install
3. https://muyiwa.medium.com/getting-started-with-clojure-and-visual-studio-
code-15ef6283c496
4. https://calva.io/
5. https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md
6. https://clojure.org/guides/learn/syntax

COMP 348 Principles of Programming Languages

17

You might also like