Music, Art, and Web Apps in Clojure 

Clojure is a programming language.

  • Modern Lisp
  • Pragmatic
  • Runs on JVM (also JavaScript!)
  • Dynamic, optionally static typing
  • Functional
  • Immutable
  • Concurrent
  • BDFL - Rich Hickey

A Modern Lisp

  • 2nd oldest high-level programming language (1958)
  • Invented by John McCarthy
  • Based on Lambda Calculus

Brief History of Lisp

  • Common Lisp
  • Scheme
  • Clojure 
  • Emacs Lisp

11+ currently maintained Lisp dialects

Lisp Overview

  • Polish Prefix Notation
  • REPL
  • LISt Processing
  • Lots of Parentheses
  • (s-expressions)
  • Pioneer of recursion, conditionals, higher order functions, etc.
  • Macros

Lisp Syntax

(defun square (x)
  (* x x)) 

(square (5)) ; => 25

(+ (* 2 3) 1) ; => 7

REPL

Lisp primitive functions

  • Read - accepts an expression from the user, and parses it into a data structure
  • Eval -  evaluates the data structure (function or list) and returns result
  • Print - prints the result back to the user
  • Loop - returns back to Read, looping until there is nothing left to read

LISt Processing

 

(setq list '(1 2 3))

(defun sum (list)    
    (if (null list) ;; conditional like JS ternary operator!
        0
        (+ (first list) 
           (sum (rest list))))) ; => 6

Everything's a list (s-expressions)

Macros

Meta programming

(defmacro inc (x)
   (list 'setq x (list '1+ x))) 

(inc 5) ; expands to (setq 5 (1+ 5))
        ; evals to => 6

Lisp in the real world

  • ViaWeb, the original e-commerce site (Paul Graham)
  • Jak and Daxter (Naughty Dog)
  • Super Mario 64 (Nintendo)
  • Emacs (GNU, Richard Stallman)
  • Aritficial Intelligence

Back to Clojure

Syntax

(defn hello [] ;; Minor differences from CL, notice defn instead of defun
  "Hello World!"
) ;; Args use square brackets

(hello) ;=> "Hello World!"

(+ (* 2 3) 1) ;=> still 7
  • Most widely-contributed-to Clojure project
  • Akin to Maven and Grunt in a way, but far more integral to development
  • Like Ruby Gems or Node modules, a Clojure library repo.
  • Clojure contrib was official but seemingly dead (or in less use than clojars)

Targets JVM and JavaScript

  • Super fast run time (at the expense of a super slow compile/start up time)
  • Compiles to JVM byte code
  • Also compiles directly to JavaScript with ClojureScript
  • Can import Java Libraries and export to .jars and .wars

Immutable

  • Basically means unchangeable
  • Can change the reference to the object or data, but not the object or data itself
  • In order for data to be modified, we must get a new copy of data 
  • Prevents unwanted modifications via inheritance, other unknown factors

Functional

  • Stateless
  • Mathematical
  • Immutable
  • Paradigm akin to OOP

Concurrent

  • Multiple simultaneous computations
  • Separate computations can interact with each other
  • Difficult, but Clojure is good at it
  • Multithreading
  • Full-stack micro-framework
  • Built on Ring middleware
  • Multiple application profiles
  • Insanely simple

Demo

$ lein new luminus lumi-demo +cljs +h2 // generate project with database and clojurescript

$ cd lumi-demo

$ 

$ lein run // start app

// Poke through the code while server starts up, go to localhost:3000


$ git clone git@github.com:luminus-framework/guestbook.git

$ cd guestbook

$ lein ragtime migrate // migrate database

$ lein run

// Again visit localhost:3000, show off database workings
  • Built on SuperCollider (sound software)
  • Live code music
  • MIDI interface
  • Freesound API

Demo

$ lein new overtone-demo

$ cd overtone-demo

$ emacs

;; add [overtone "0.9.1"] to :dependencies in project.clj

$ lein deps

;; cider-jack-in or $ lein repl

Demo

;; overtone-demo/core.clj
(ns overtone-demo.core
  (:use
   [overtone.live :refer :all])

(def hihat (sample (freesound-path 250530)))
(def kick (sample (freesound-path 2086)))
(def snare (sample (freesound-path 212208)))

(defonce met (metronome 180))

(defn drum-loop [m beat]
  (at (m (+ 0 beat)) (kick) (hihat))
  (at (m (+ 0.5 beat)) (hihat))
  (at (m (+ 1 beat)) (snare) (hihat))
  (at (m (+ 1.5 beat)) (hihat))
  (at (m (+ 2 beat)) (kick) (hihat))
  (at (m (+ 2.5 beat)) (hihat))
  (at (m (+ 3 beat)) (snare) (hihat))
  (apply-at (m (+ 4 beat)) drum-loop m (+ 4 beat) [])
)

(drum-loop met (met))
  • Built on Processing (graphics software)
  • Live code visuals
  • 2d and 3d
  • Interactive and animated

Demo

$ lein new quil-demo

$ cd quil-demo

$ emacs

;; add [quil "2.2.5"] to :dependencies in project.clj

$ lein deps

;; cider-jack-in or $ lein repl

Demo

;; quil-demo/core.clj
(ns quil-demo.core
  (:require [quil.core :as q]))

(defn setup []
  (q/smooth)
  (q/frame-rate 30))

(defn draw []
  (q/stroke (q/random 255) (q/random 255) (q/random 255))
  (q/stroke-weight (q/random 50))
  (q/fill (q/random 255) (q/random 255) (q/random 255))

  (let [diam (q/random 180)
        x    (q/random (q/width))
        y    (q/random (q/height))]
    (q/ellipse x y diam diam)))

(q/defsketch demo
  :title "Random colorful circles"
  :setup setup
  :draw draw
  :size [1292 800])

Overtone + Quil

Demo

$ lein new quilover-demo

$ cd quilover-demo

$ emacs

;; add [quil "2.2.5"] and [overtone "0.9.1"] to :dependencies in project.clj

$ lein deps

;; cider-jack-in or $ lein repl

Overtone + Quil

Demo

;; quilover-demo/core.clj
(ns quilover-demo.core
  (:require [quil.core :as q]
            [overtone.live]))

(defn setup []
  (q/smooth)
  (q/stroke-weight (q/random 50))
  (q/fill 150 50)
  (q/set-state! :mouse-position (atom [0 0])))

(def boing (sample (freesound-path 140867)))

(defn draw-circles []
  (dorun
   (for [i (range 0 300)]
     (let [x      (q/random (q/width))
           y      (q/random (q/height))
           radius (+ (q/random 100) 60)]
       (q/ellipse x y (* 2 radius) (* 2 radius))
       (q/stroke (q/random 255) (q/random 255) (q/random 255))
       (q/fill (q/random 255) (q/random 255) (q/random 255))
       (q/ellipse x y (q/random 500) (q/random 500))))))

(defn capture-click []
  (let [[x y]  @(q/state :mouse-position)]
    (boing)
    (draw-circles)))

(q/defsketch gen-art-30
  :title "Click Boing Shapes"
  :setup setup
  :mouse-pressed capture-click
  :size [900 600])

Other Sources

Art, Music, and Web Apps in Clojure

By Michael Elliott

Art, Music, and Web Apps in Clojure

  • 3,069