Functional Programming with Clojure


Sam Popowich

@redlibrarian

Programming Paradigms

  • Imperative
  • Object Oriented
  • Functional

#include <stdio.h>

int main(){
  int age;
  printf("Please enter your age: ");
  scanf("%d", &age);
  age += 5;
  printf("In five years you will be %d years old.\n", age);

  return 0;
}
              

>> Please enter your age: 10
>> In five years you will be 15 years old.

class Student
  def initialize(name, age)
    @name = name
    @age = age
  end

  def years_old
    puts "I am #{age} years old."
  end
end

class School
  def initialize
    @students = []
    names = ["Belinda", "Jane", "Charlotte", "Gina"]
    names.each do |name|
      students << Student.new(name, 15)
    end
  end

  def students
    @students.join(",")
  end

  def student_ages
    for student in @students
      student.years_old
    end
  end
end
             
Clojure:

(defn is-prime? [n] (every? false? (map #(= 0 (mod n %)) (range 2 (Math/sqrt n)))))
              

Ruby:
def is_prime?(num)
  return false if num <= 1
  Math.sqrt(num).to_i.downto(2).each {|i| return false if num % i == 0}
  true
end

What is Clojure?


  • It's a LISP (What's a LISP?)
  • Invented in 2007 by Rich Hickey
  • Hosted language (on the JVM)
  • Has all LISP functionality, plus access to Java language
  • Functions are first-class objects (what does THAT mean?)

What's a LISP?

LISP: LIst PRocessor


  • Invented in 1958 by John McCarthy at MIT
  • Uses s-expressions as both code and data
  • Many dialects...
  • Common LISP
  • Scheme
  • Clojure
  • Lambda-Calculus
  • Turing Machine

What does it mean to say that functions are first-class objects?

In practice, a first-class object can be...

  • passed as an argument
  • returned from a function
  • assigned to a variable

In imperative programming, scalar data types (integers, characters, etc) are usually first-class


In object-oriented programming, objects are first-class


In functional programming, functions are first-class

So, in imperative programming, we manipulate scalar data, in OO we manipulate objects, and in functional programming we manipulate functions

Wait a minute, what's a function?

A function is a procedure that returns a value


(defn double [x] (+ x x))
>> (double 5)
>> 10
              

(defn first-word [sentence] (first (clojure.string/split sentence #" ")))
>> (first-word "Now is the winter of our discontent")
>> "Now"
              

How is this useful?


  • Everything is a function
  • Functions and their values are interchangeable
  • We can get rid of variables
  • No variables, no state
  • Why is state bad?
  • Side-effects vs. pure functions
  • Testing

Homoiconicity

Code and data are expressed as functions


Referential Transparency

Functions and values are equivalent and interchangeable


Immutability

Data objects never change (no variables)

Given that (defn ten [] (double 5)) and 10 are equivalent and interchangeable, then it's clear that our code and our data are expressed in exactly the same way.


This has major implications for the way we think about and work with our data.

Example: Working with XML

calendar.xml



  
    International Lefthanders Day
    
      August
      13
    
  
  
    Rover's birthday
    
      October
      12
    
  
  
    Groundhog Day
    
      February
      2
    
  
  
    Kamehameha Day
    
      June
      11
    
  


(use '[clojure.xml :only (parse)])
(def xml-doc (parse (java.io.File. "calendar.xml")))
(keys xml-doc)
>> (:tag :attrs :content)
(:tag xml-doc)
>> :calendar
(count (:content xml-doc))
>> 4
(:content (first (:content (first (:content xml-doc)))))
>> ["International Lefthanders Day"]
(type xml-doc)
>> clojure.lang.PersistentStructMap

Example taken from http://gettingclojure.wikidot.com/cookbook:xml-html (slightly modified)

REPL-based development

  • Read - Evaluate - Print Loop
  • evaluates expressions, returns values
  • LISP tradition
  • Code as data: modify running code
  • Leiningen (leiningen.org)

Thanks!