|
A function is an entity that receives "things" and return a "thing".
The beauty of functional programming is that the "things" that functions receive and return can be anything - including functions
In functional programming, functions are first-class citizens.
There are 3 ways to define a function and one way to call a function:
fn
:
(def foo (fn [a b c] a))
(foo 1 2 3)
#
:
(#(+ %1 %3) 1 10 100)
defn
, you can add a documentation string to your function:
(defn bar "bar is a function with documentation"
[a b c] b)
(bar 1 2 3)
defn
is a macro that associates metadata to the function that it defines:
(defn bar "bar is a function with documentation"
[a b c] b)
(meta #'bar)
(:doc (meta #'inc))
(defn hello [name])
(defn zero-check [n])
Write a function called applicator
that receives two arguments: a function and a "thing" and returns the application of the function on the argument.
(defn applicator [func number])
(= (applicator inc 19) 20)
In clojure, Lists
are simply linked lists.
(list 1 2 "hello")
(list 1 2 (list "a" "b") (list 1.2 (list 3.43243 2.5)))
'
.
'(1 2 ("a" "b" (1 2 4)))
(rest '(1 2 3 4 5))
first
:
(first '(1 2 3 4 5))
(cons 1 '(2 3))
count
the elements of a list:
(count '(1 2 3 4 5))
(defn fifth [lst])
(fifth '(1 2 3 4 5 6 7 8))
Write a function that receives a number n
and a list and returns its n
th element. You'll need to use recursion.
(defn nth-element [lst n])
(nth-element '(1 2 3 4 5 6 7 8 9 10 11) 10)
Write a function called select-1-5-7
that receives a list and returns a list with the elements of the original list at position 1 5 and 7.
nth-element
or the clojure nth.
(defn select-1-5-7 [lst])
Vectors
are like Lists
but with fast random access. vector
(vector 1 2 3 4 5)
[]
[1 2 3 4 "aa" [1 2] [1 2 3]]
Lists
, you can access the first element with first
:
(first [1 2 3 4 5])
(get [0 1 2 3 4 5 6 7 8 9 10] 7)
list
into a vector
with vec
:
(vec '(1 2 3 4 5))
(defn ->list [vec])
(defn present? [vec thing])
Maps are associative arrays (sometimes called dictionaries).
Basically maps are key-value based collections.
There are a couple of ways to create a map:
With hash-map
:
(hash-map :a 2 :b 3 :c 4 :d 5 :e 6)
With the map brackets literals {}
:
{:a 1 :b "aa" :c 'a}
Pay attention that there is no meaning to the order of the elements inside a map.
Also, if you set a key twice, one will override the other.
Maps can be nested:
{:x {:a 1 :b "aa" :c 'a} :y [1 2 {:a 3}]}
Keys and values can be of any types: lists, vectors, keywords, regexps and even maps and functions!
'{:email #"^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$"
(1 2 3 4) list
[1 2 3] vector
{:d 1} map}
With zipmap
, you set the keys and the values separately:
(zipmap (range 10) (range 100))
With (into {})
, you can convert a 2d
array into a map:
(into {} [[:a 2] [:b 3] [:c 4] [:d 5] [:e 6]])
What methods don't support nested maps creations?
How many keys are there in this map: {[1 2] :aaa '(1 2) :aaa}
?
How do you generate an empty map?
With assoc
, you associate (create or modify) one or more key-value
s
(assoc {} :a 1 :b 2)
With dissoc
you dissociate (remove) one or more key-value
s
(dissoc {:a 1 :b 2} :a :b)
With assoc-in
, you associate a nested key-value
(assoc-in {} [:a :b :c] 1)
What will happen with (assoc-in {:a 1} [:a :b :c] 1)
?
There are a couple of ways to retrieve values from a map:
get
(get {:a 1 :b 2} :a)
When they key is not there, get
returns nil
:
(get {} :a)
Meditate about this problematic code: (get {:a nil} :a)
What happens if you pass an additional argument to get
?
get-in
(get-in {:a {:b 1}} [:a :b])
find
(find {:a 1 :b 2} :a)
the map itself is a function
({:a 1} :a)
keywords are functions
(:a {:a 1})
You can retrieve the keys of the map with keys
(keys {:a 1 :b 2 :c {:d 1}})
And the values with vals
(vals {:a 1 :b 2 :c {:d 1}})
Write an assertion using keys
, vals
and zipmap
.
Write a function that returns the values for a selected collection of keys
(defn my-select-keys [m the-keys])
(= (my-select-keys {:a 1 :b 2}) [:a :b :c] '(1 2 nil))
Write a function that receives a map m
and a function f
and returns a map with the same keys as m
and with the values transformed by f
:
(defn map-object [f m])
(= (map-object #(* 100 %) {:a 1 :b 2 :c 3}) {:a 100 :b 200 :c 300})
Write a function that converts a sequence into a map where the keys are the indexes of the elements in the sequence.
(defn sequence->map [s])
(= (sequence->map [10 20 30]) {0 10 1 20 2 30})
Write a function that checks if a map is a submap of the other.
Map m1 is a submap of m2 if all key/value pairs in m1 exist in m2"
(defn submap [m1 m2])
[(true? (submap {:a 1 :b 2} {:a 1 :b 2 :c 3}))
(false? (submap {:a 1 :b 2 :c nil} {:a 1 :b 2}))]
Set is a fundamental concept of mathematics.
To create a set
from a collection, you use set
:
(set '(1 "hello" [1 2]))
In a set, there are no duplicates
(set [1 1 "hello" "hello" [1 2] '(1 2)])
Why [1 2]
and (1 2)
are considered as duplicates?
You can also create a set with the set literal #{}
#{1 2 "hello" [1 2]}
But then, duplicates are forbidden!
#{1 2 3 1}
What's the difference between set
and distinct
?
(distinct [1 1 "hello" "hello" [1 2] '(1 2)])
You can also use (into #{})
to create a set
(into #{} [1 2 3 3 4])
In order to use the functions on sets, we have to require the clojure.set
namespace:
(require '[clojure.set :as s])
Why is there a quote in the require
statement?
All the basic mathematical operations on sets are available:
Union
(s/union #{1 2} #{2 3} #{4 5 2})
Intersection
(s/intersection #{1 2} #{2 3})
Difference
(s/difference #{1 2 3 4 5} #{1 2} #{3 4})
You are on your way to become a clojure
expert:
You already know about:
/