Skip to content

Latest commit

 

History

History
1682 lines (1153 loc) · 67.3 KB

notes-for-clojure-practicalli.org

File metadata and controls

1682 lines (1153 loc) · 67.3 KB

Practically Clojure

Clojure Overview

You are not alone in thinking Clojure feels weird when you write it, we all feel this at first

David Is it posible to come up wht an algorightm to prove we know everything in maths

Generated lambda calculus & the universal turing machine

Lambda calculus begat

  • Lisp
  • ML
  • Haskell
  • Clojure

Turning machine begat

  • COBOL
  • Algol
  • Basic
  • C / C++ …

General thoughts

Better to have one data structure with many functions acting upon it, rather than many data structures.

You do need constraints with data however data does not need to be wrappped up in types and classification theory to do so.

Phil Bagwell created immutalbe data structures with data sharing in early 2000 and this is the basis for Clojure’s persistent data structures (eg all of them)

In OO languages the class is there to stop you doing things and accessing data in an unsafe way. Clojure allows you to access data in a managed way so you dont need that protection.

Data tends to arrive in bulk

Clojure is about expresivity and performance. Its a lisp for getting real world work done in. You dont have to go very deep to understand the core of clojure. Simply use (source fn-name). You are only one or two levels above the core library

Installing Clojure

Pre-requisits

Clojure runs on the Java virtual machine (although there are versions that run on the Microsoft CLR and JavaScript V8 engine)

Installing Java on Ubuntu You can use OpenJDK on Ubuntu and Clojure will work just fine. However, you make get better performance using the Oracle JDK. Java JDK 1.6 or 1.7 is recommended (until Java 1.8 has been released)

1.) If you’ve already installed OpenJDK in Ubuntu Software Center. Remove it by running this command:

sudo apt-get purge openjdk*

2.) To add the ppa, run:

sudo add-apt-repository ppa:webupd8team/java

Then update the Ubuntu package list:

sudo apt-get update

3.) Then install the desired version of Oracle Java using ONE of the following commands

sudo apt-get install oracle-java8-installer sudo apt-get install oracle-java7-installer sudo apt-get install oracle-java6-installer

Clojure is a library

  • you dont need to install Clojure directly, it is used as a library in your Clojure projects.

Developer tools

Leinignen

Introduction

Leiningen is used to manage the project build process (compilation, etc). By using Leiningen there is no need to install Clojure itself, as Leiningen will manage all dependencies including Clojure.

LightTable uses a library called … to call out some of its actions to Leiningen, such as starting a REPL session.

Leiningen is used to generate projects in a standard structure. It can also package your project into a Jar file for distribution (or Uberjar if deploying to a Java environment without Clojure)

On the command line you should be able to run the leiningen command and see the available tasks it can run for you.

lein

Leiningen requires Java software development kit (SDK) 1.6 or greater to be installed, the Java runtime edition (JRE) that comes with most operating systems is not enough.

You should be able to run the following commands successfully in a command window

java -version javac -version

If the first command fails, you need to install or configure the Java runtime edition (link) If the second command fails, you need to install or configur the Java SDK (link)

Tweaking REPL prompt
BLOG: Add Colour to your Clojure REPL with Leiningen and ASCII codes
Managing developer dependencies
local profiles
  • add the plugins that you use across all projects by default
  • useful for specific developer tooling that is typically unique to a developer
project profiles
  • include plugins that are only used during development and not needed for run time
  • eg. testing frameworks
Using Local Repositories (eg. Maven)

Lein Install

  • places jars into local repo and link check repo firs when doing dependency checking [TODO: needs reading up on]
Leiningen Plugins to consider
lein-ancient - analyzes your project.clj and lets you know which dependencies are out of datelein-exec - directly execute Clojure code snippets, or write shell scripts in Clojure!lein-try - start a REPL with various dependencies without needing a project. Great for exploring new libraries!Eastwood - a lint tool for Clojure.lein-heroku-deploy - simplify your Heroku deploy
  • The heroku deploy plugin will
    • activate maintenance mode
    • push your app to heroku
    • restart app
    • deactivate maintenance mode
    • warm up app
lein-vanity - Simple lines of code statistics generatorlein-webrepl - REPL in a browser, based on ringMonlein-clique - Makes a graph of dependencies between functionslein-cucumber - running clojure-based cucumber-jvm specificationslein-midje - runs both Midje and clojure.test testslein-release - automatically manages your project’s version and deploys the built artifact for youlein-debian - make debian packages of project buildslein-idefiles - Generate IDE files for Leiningen projectslein-html5-docs - generates HTML5 API docs for your Clojure project from the project metadata rather than parsing the codelein-grep - renders meaningful search results in table formatlein-create-template - creates a Leiningen project template from an existing skeleton projectslein-autoreload - Keep the repl up to date with source changes
Automatically set REPL settings to manage level of output

[2013-08-29 Thu] file:~/Dropbox/emacs-for-clojure-developers/manuscript/wip.md::<!– Do you have to set these each time you enter a repl? Is there a way to have these by default ? –>

Light Table 5.x

Install latest 5.x version
INSTALLED: version 0.5.2 in apps folder on Lenovo from http://www.lighttable.com/
Read the built in Docs
Using LightTable
Pre-requisitsJava 1.6 or greater

Java SDK version 1.6 or higher required.

You need more than just the Java runtime (JRE). Check you have javac on your OS execution path

In a terminal / Command window type:

javac -version

Leiningen - the Clojure project automation tool See the previous section on LeiningenWorking with projects

(See my JAXLondon-2013 slides on LightTable)

Create an Instarepl session

  • connects to a default REPL session

Open the project folder

  • Open files from that folder, eg. namespace.core
  • Evaluate namespace.core
  • Alternatively connect a repl to the namespace.core file (effectively same as above)

Emacs & Emacs Live

  • configure Emacs using eLisp helps you practice your Clojure
  • Emacs live gives you a comprehensive Clojure setup instantly
Emacs commands

C-x C-f – open file or folder C-x f – open recent file M-x delete-frame – close a frame window M-x 0 – close buffer window M-x new-frame – opens a new frame window Tab – use tab anywhere on a like to line up your code

Clojure commands

nrepl-jack-in nrepl-close ;; close your connection nrepl-interupt ;; stop your repl going crazy nrepl-restart nrepl-rotate-connection nrepl-return

M-x nrepl –quit – not sure about this one M-x nrepl-jack-in – start a new REPL and connect to it M-x nrepl – connect to an already running REPL M-x nrepl-close – close an existing REPL that the current buffer is connected to

Running Clojure code

When working with the REPL you can run your code by evaluating, either by individual expression or by the whole file of code.

C-M-space – highlight the next expression, ahead of the current cursor position C-x C-e – evaluate this expression (put cursor at end of line) C-c C-k – evaluate the whole buffer, this loads additional namespaces into the REPL (eg. loads in Overtone and starts the overtone.live server)

ParEdit

M-s delete surrounding brackets

Emacs with Clojure & Overtone

Emacs uses nrepl to start and connect to a Clojure REPL. Simply open a clojure file in the project you wish to run the REPL in and run the command nrepl-jack-in

M-x nrepl-jack-in

Keyboard combo: C-c C-j (this is one I configured myself)

The nrepl-jack-in command calls leiningen, which then runs and reads in the project configuration from the project.clj file. Once leiningen creates the REPL then Emacs opens a buffer window with the REPL prompt. You can now run Clojure code in this REPL buffer.

Starting Overtone

Although the REPL is running, you are not ready to use overtone just yet. First you need an overtone server.

You can use a local overtone server or the remote Overtone supercollider (assuming you have an Internet connection). We can tell the running REPL to use a local overtone server typing the following Clojure expression into the REPL buffer

(use ‘overtone.live)

Alternatively, if you open a Clojure file for your Overtone code and add (:use [overtone.live]) to the namespace then you can evaluate that Clojure file and it will start a local overtone server. To evaluate the Clojure file use the keyboard combo

C-c C-k

Evaluate all code

As you have just seen, you can evaluate all the code in a clojure file using the keyboard combo: C-c C-k

So when you are writing your clojure code to drive Overtone, you can use this keyboard combo to load in any new or updated function or data definitions (defn and def expressions).

Evaluate code in-line

If you just make a simple change to your code then you can evaluate a single expression. Place the cursor at the end of the expression and use the command … or keyboard combo:

M-x .... C-x C-e

This will read and evaluate the expression and update the REPL runtime environment with any changes. So if you modify a def or defn expression, evaluating it makes it available to use.

If you just want to call a function you can also use this keyboard combo too. For example, if you have a function called foo, you can define an expression that calls it

(foo)

and then place your cursor at the end of that expression and use the C-x C-e combo to call the foo function and return any result (or side-effects).

changing the font face on emacs to make it all bigger, rather than just the text in buffers – TODO google this

IRC in Emacs is erc

Eclipse & Counterclockwise

IntelliJ

Sublime text

Sublime Text is a popular text editor that runs on Linux, Mac and Windows. It is a lightweight approach to writing Clojure and has basic syntax highlighting.

The developer workflow would be to write Clojure in Sublime and run your Clojure code in the REPL using Leiningen on the command line. Alternatively you could write your Clojure code in the REPL and copy/paste it into files using Sublime text.

A simple approach, but quite limted in terms of developer experience.

Netbeans

Although there is a plugin for netbeans, at the time of writing that plugin was not being actively supported or developed.

Learning via the REPL

Special REPL stuff

last three results *1 *2 *3

Errors *e

Namespaces

When adding functions to your namespace, you need to choose if that function is addd to the current namespace or you shoould refer to it from its existing namespace (or an alias shorthand).

If you are only going to uses a few functions, then you only need to mame them accessible.

If you are using a framework (eg. overtone) then you may want to include the whole set of fuctions.

If you add a function to your namespace, then you can simply use its name to call it, no need for a fully qualified namespace as it is now part of the current namespace.

So if you (:use ‘clojure.string) in the user namespace you can call (split “string to split”) rather than have to call (clojure.string/split “string to split”)

The thing to be weary about with use is that it will pull in all functions and over-ride any existing function defintions if there are duplicates. You can see what happens when you add functions from other namespaces by adding the :verbose keyword to your namespace definitions.

(ns my.namespace :use overtone.live :verbose)

adding functions with :require … :refer … is a more sutble approach to working with namespaces

require fully-qualified.namespace – allows you to call a function using its original fully qualified namespace

require fully-qualified.namespace :as alias – call a function using alias/function-name rather than fully qualified namespace

require fully-qualified.namespace :refer [function-name] – call function by name only, does not include function if it is already defined in the namespace [TODO - check]

use fully-qualified.namespace – adds all functions from namespace to current namespace, over-writes if there are dubplicates already in the namespace

use fully-qualified.namespace :only [function-name] – only pulls in the specific function name, over-writes if it exists already in the namespace [TYODO: check]

:use [fully-qualified.namespace :rename {function-name alias-function-name]] [:use [clojure.contrib.math :rename {sqrt ccm-sqrt}]] – pulls in the named functio and changes its name… this

— refer and rename example – not sure about this one (ns foo (:require clojure.data.zip) (:refer [clojure.data.zip :rename {ancestors xml-ancestors, descendants xml-descendants})

Quick fix

; Define a new namespace (ns my-namespace.filename)

; Define new namespace, your code will use functions & defs from another file / library ; need to (ns my-namespace.filename

require other-namespace.filename)

;; need to specify fully qualified names for any functions or defs

; as above but specifying an alias for the external namespace (ns my-namespace.filename :require other-namespace.filename :as alias-name) ;; qualify any def or defn with the alias name

; include external files / libraries into the current namespace (ns my-namespace.filename :require other-namespace.filename :refer :all) ;; external defs & defns do not need to be qualified, they become part of the current namespace ;; eg: :require clojure.string :refer :all - you can then use string without any qualifier ;; Note: need to make sure you dont get namespace conflicts

; alternative syntax for the above (ns my-namespace.filename :use other-namespace.filename)

;; refinements on what functions are pulled in from a library ;; exclude ;; include-only

You can use clojure functions only if they are added to the namespace. By default, clojure.core and java.lang are included in the REPL or any new project The require function is needed in this case. For example:

user=> (clojure.string/split “comma,seperated,values” #”,”) [“comma” “seperated” “values”] user=>

user=> (use ‘[clojure.string :as str :only [join split]]) 2 nil 3 user=> (str/replace “foobar” “f” “p”) 4 “poobar”

Difference between :use and :require Use will over-write any existing vars / symbols (def, defn) with any dupliace vars from the additional namespace. Require will not over-ride any vars, just ignore them?

Flags - from (docs require)

A flag is a keyword. Recognized flags: :reload, :reload-all, :verbose :reload forces loading of all the identified libs even if they are already loaded :reload-all implies :reload and also forces loading of all libs that the identified libs directly or indirectly load via require or use :verbose triggers printing information about each load, alias, and refer

Example:

The following would load the libraries clojure.zip and clojure.set abbreviated as ‘s’.

(require ‘(clojure zip [set :as s]))

Use Convienience function instead of :require namespace :refer

:exclude list-of-symbols :only list-of-symbols :rename map-of-fromsymbol-tosymbol

Namespaces in Clojure are a way to group related behaviour together. Think of it as a logical grouping like packages in Java & C#. Each source code file in Clojure has its own namespace, which related to the filename and folder structure for that source code file.

When clojure runs it does so within a specific namespace, even when you are in the REPL. Using a namespace allows you to call functions by name from within the namespace.

When you run a REPL you will see that you are in the user namespace.

You can change to a new namespace using

(ns ‘namespace.name)

where namespace.name is the name you want to call your new namespace.

The namespace name should be quoted so that Clojure understands it is a piece of data rather than something to evaluate. By convention, the single quote character ’ is used to quote the namespace name.

Tip: It is common practice to use the in-ns function rather than ns. o change between namespaces.

If you wish to use functions outside the current namespace, you need to tell Clojure to include them. Including other namespaces is often used when writing unit tests, including existing libraries or any application development that is bigger than one source code file.

There are a few different approaches to including other namespaces

(ns namespace.name)

This namespace definition relates to the way source code files are structured.

The last part of the namespace is the name of the file the source code is saved in.

The rest of the namespace is the folder structure.

(ns folder.filename)

(doc use) (ns some.namespace (:require [clojure.contrib.json :as json]) (:use [clojure.string :only [trim lower-case split]] [clojure.contrib.shell-out] [clojure.pprint] [clojure.test]))

Phil Hagelberg (Leinginen author) comment on namespace syntax ;; brackets imply that all entries should be indented as peers: (:import [java.io File] [org.apache.maven.artifact.ant Authentication DependenciesTask RemoteRepository]))

;; while parens imply that the first element is special and only the ;; ones after it should be indented as peers: (:import (java.io File) (org.apache.maven.artifact.ant Authentication DependenciesTask RemoteRepository)))

Including libraries & other namespaces

To use functions outside of the current namespace you are in, you need to refer to them first.

In the repl you can simply enter an expression using require or use function as follows:

(require ‘namespace.name) (require ‘namespace.name :refer :all) (use ‘namespace.name) (:use [namespace.name]) (:use [namespace.name anonther-namespace.name])

Using require allows you to refer to external functions, although you still need to specify the full Namespaces

In a project file, you can include other namespaces inside the namespace definition for the Clojure file you are working on.

(ns namespace.name require ‘namespace.name)

(ns namespace.name require ‘namespace.name :refer :all)

(ns namespace.name use ‘namespace.name)

(ns namespace.name :use [namespace.name anonther-namespace.name])

(ns foo.bar (:refer-clojure :exclude [ancestors printf]) (:require (clojure.contrib sql combinatorics)) (:use (my.lib this that)) (:import (java.util Date Timer Random) (java.sql Connection Statement)))

Reloading Namespaces

As you work on your Clojure code you will add new namespaces and perhaps even change existing namespace names.

In order for your REPL session to pick up these changes you can either restart the REPL (slow) or ask the REPL to reload a Namespaces. If you are working with a Leiningen project you can also ask the REPL to reload all the Namespaces in the project.

Simply add the :reload keyword to the require, us or ns functions we have previously seen.

(require :reload ‘namespace.name) (use :reload ‘namespace.name)

By adding the reload keyword to a Leiningen project, then .... [TODO: how does reload work with projects?]

(ns namespace.name :use [namespace.name anonther-namespace.name] :reload)

Working with projects

Create a new project with Leiningen

Managing Dependencies

Running a REPL for the project

Inside the top level folder of your Clojure project (where there should be a project.clj file), run

lein repl

Running a project

Defining an entry point to the app

Namespaces

Cover this later ??

Use and require

Use pulls everything into the namespace automatically

  • you can specifiy a namespace alias using :as if there are naming clashes with symbols (def, defn, etc) and keywords

Require does what then ??? It tells your project about the libraries but only brings them in if you specify …

Learning the language syntax

Prefix notation

Unlike other languages, Clojure uses prefix notation for everything. Languages such as Java and C# are predominantly prefix notation, but switch to infix notation for numerical calculations

Java / C# methodName(param, param) 1 + (2 * (3 * 3) / 2)

Clojure (function param, param) Numerical operators such as + / * - are functions in Clojure

Types

Yes there are types in Clojure, even though its a dynamic language and you dont explicitly define types when you write code.

; my code does… ; Comment 123456789 ; Long 1234567898765432N ; Arbitrary precision integer 1.234 ; Doubles 1.234M ; Big decimals 22/7 ; Ratios (Rational numbers) “chunky bacon” ; Strings chunky bacon ; Symbols :chunky :bacon ; Keywords true false ; Boolean nil ; Null #”^chunky\s+bacon$” ; RegExp \A \b \u2603 ; Characters

Keywords

First class citizens Its like an immutable string that refers to itself When a keyword is compiled it is assigned a unique

Sequences

Sequences are persistent data structures in Clojure and include List, Vector, Map and Set.

All these types of data structures are immutable, meaning that once they are defined they cannot be altered (like using the keyword Final in other languages).

If you use a function on any of these persistent data structures that modifies the data it holds, a new sequence is returned rather than altering the original sequence. The new sequence is not a complete copy, however it is a reference to the original sequence plus the changes to the original sequence (similar to a diff ?).

If you want to give the appearance of modifying a sequence, you can redefine the name (var) that points to the original sequence to the new sequence generated.

So sequences are immutable, however the names you can attribute to them can change.

Sequence library of functions

The sequence library is very large…

first

Get the first element in the sequence

(first ‘(1 2 3 4)) => (1)

rest

Get all the elements except the first

(rest ‘(1 2 3 4)) => (2 3 4)

cons

Construct a new sequence from the original and the additional values supplied

(cons ‘(1 2 3) 4) => (1 2 3 4)

Creating Sequences
range

Create a sequence from a range of numbers (TODO: check if just for integer or also decimal, what about characters?)

;; Not sure what happend here. Tried to create a sequence from 0 to 1 at 0.1 intervals ;; Is there some rounding going on? not sure why its not ;; 0 0.1 0.2 0.3 0.3 0.5 0.6 0.7 0.8 0.9 ;; output seems consistent when ran for second time user=> (range 0 1 0.1) (0 0.1 0.2 0.30000000000000004 0.4 0.5 0.6 0.7 0.7999999999999999 0.8999999999999999 0.9999999999999999) user=>

Sequences in the REPL

When you evaluate functions in the REPL that work on Vectors you may get a list displayed as a result.

This is because the result of the function is a sequence and the REPL displays all sequences as lists. The actual result is still a vector and this can be checked using (class …) around your function to check the type returned.

Collections

Lists

(quote (:a :b :c)) (list …)

Vector

[]

Performance differences from lists - acts like an array, although its not an array

Lists are a linked list Vectors occupy a fixed set of memory

Maps

have a literal syntax and are easy to define

small maps are array-map

hash-map

sorted-map

Sets

Although sets are backed by the same kind of algorytim as maps, they have a slightly different behaviours

#

quiz

{:inventory #{“axe” “key”} , :room {:name “Billard room”} , :exits [:North : South]}

Exercises

create a data representation of a hand of cards

Prefix notation

Parentesis were invented to solve the problem with operator precidence.

For example, if you multiply something and add something, then without parentheses you have to remember to multiply first.

By using prefix we elimanate any confusion in order precidence. Prefix notation is also easy to convert into a an abstract syntax tree without us getting fooled by the order.

Function application

The first item

Everything is a list

Homoiconicity explained

Clojure is defined using a list. Each item in a list can be a list itself.

The first item in a list is a function (unless you explicitly tell Clojure otherwise by using quote ‘)

Clojure collections

The List collection type

You have already seen that the list is the basis of the syntax for Clojure. It is not surprising then that the list is also a very common data structure in the language.

The list data structure has the following properties

Defining a list

(list 1 2 3 4) (quote(1 2 3 4)) ‘(1 2 3 4)

Adding to a list

The Map data structure type

The Vector collection type

The Set collection type

Defining data structures

Defining behaviours

Defining a named function

Definng an anonymous function

Shorthand for anonymous functions

Using the # character before a list is a simple shorthand for defining an anonymous function

#(* 1 2 3 4 5)

To pass a paramter into an anonymous function, use the % character

To specify individual paramters you can number the % characters like:

#(* 10 %) #(* 10 %1 %2 %3)

Calling functions

Defining functions with different airities (runtime polymorphism)

(defn hello-params ([] “Hello to no-one”) ([name] (str “Hello ” name) ([name & others]) )

namespaces

use pulls everything in from the stated namespace and adds it all to the current namespace, unless you define only. Use is a shorthand for :require :refer :all

Require makes available the functoins from the namespace, but does not pollute your current namespace. However, if you use the :refer :all keywords with :require then it will add everything to the namespace.

You can us :as to map to the namespace to an alias, helping avoid any function name (symbol) clashes

Case

Should only use case with real constants as things are evaluated/interpreted/generated by the reader

Sequence / List Comprehension

  • working with multiple lists, generating a single list as output

Using the For macro

  • ClojureDocs - for
  • (for [number [1 2 3]] (* number 2))
    • iterate over every value in the var number, applying the function to multiply the number by 2
  • simple example that can also be done with map
    • (map #(* % 2) [1 2 3])
      • map the function over the dataset
      • map each number to the function to times the number by two. % is the placeholder for each number and [1 2 3] is the vector containing the data)

the for function and use of map in the example above are similar. In many cases the for function provides clearer code

Filtering lists with :when

Examples of List comprehension

  • Merging data structures
    • (for [number [1 2 3] letter [:a :b :c]] (str number letter))
    • join each number and letter when iterating over each data set
  • three combination lock with filter, combinations produced should have 3 unqiue numbers
    • (for [tumbler-1 (range 10) tumbler-2 (range 10) tumbler-3 (range 10) :when (or (not (= tumbler-1 tumbler-2)) (not (= tumbler-2 tumbler-3)) (not (= tumbler-3 tumbler-1)))] [tumbler-1 tumbler-2 tumbler-3])
Genarating unique voucher codes
Generating WiFi passwords
  • for example you are at a venue where you need to trace what people have access to the WiFi and you do so by issuing a unique code to each person. This is typically the case at places like Universities
    • use the :when filter to skip letters and number that could be confused with each other, eg, i+1, 0+O, etc.

Patterns of Clojure code

Maps and functions – including maps of maps and vectors of maps or perhaps vectors of vectors

Defining data structures

Defining functions

  • group behaviour together
  • define a function name, define a functions parameters - including any arity based polymorphism define the behavior in the function – from a simple expression, to multiple expressions, to functions as paramters of functions, to recursively calling the same function – using doto or threading macro to make code readable

Learning Clojure core

Learning the most common functions in Clojure core, organised by characteristics (take clues from Clojure Koans)

Working with simple data

Range get a range of values http://clojuredocs.org/clojure_core/clojure.core/range

Example, say we wanted a range that did not start at 0 to represent a deck of cards. A deck of cards starting at 2 assuming we are not counting Ace as 1.

We could use range to create a range of number from 0 to 9, then apply a function to that range that incremented each number in turn by 2.

(take 10 (range)) ;; generate an infinate number of integers and take just the first 10.

As range is lazily evaluated, then this code is efficient.

We can also call range with a parameter defining the number of integers to generate

(range 10)

To represent the deck of cards starting at 2, then we could use a function that adds 2 to any number we pass it. For example

(fn (+ 2 %))

To apply this function to the range we are generating, we can use the map function as follows:

(map (+ 2 %) (range 10))

This will generate the numbers from 2 to 11 (range 10 gives 0-9 remember). For representing cards then we dont need a number 11, so we can shorten the range by generating 1 less number with range.

(map (+ 2 %) (range 9))

To make this even easier, range also allows us to define a start and end points for the range of numbers, so we can simplify the above by just using range

(range 2 11)

user> (range 2 11) (2 3 4 5 6 7 8 9 10)

Note that the starting number is inclusive, so it will include 2 in this case. The final number is exclusive, so in this case 11 is not included.

Working over collections

map / apply

Examples of lazyness

take / drop / repeat / range / filter

Predicates - is something something…

odd? / even? / nil?

identity

Recursion

Using recur

Polymorphism by Arity example

Range is a function that shows how clojure can have polymorphic functions based on the number of arguments (the arity) used to call the function.

Enter the following function call in the REPL to see the source code of the range function:

(source range)

Lets review the different behaviour that is run based on the number of arguemnts used to call the function.

;; The default behaviour when you call range without any arguments is to generate and infinate number of integers. Actually this calls range with three aruguemnts, rather than any specific behaviour itself. This version does however set the end number to be infinity, so the generation will go on forever. As this is a lazy function then there are no performance issues so long as you set a constraint around this call (eg (take 100 (range)) will constrain range to only generate the first 100 numbers.). Without constraint you can blow the stack of the Java Virtual Machine. ([] (range 0 Double/POSITIVE_INFINITY 1))

;; Calling range with one or two argument also calls the version of range with three arguments, using default values for the missing arguments ([end] (range 0 end 1))

([start end] (range start end 1))

;; The version of range with three arguments defines the majority of the behaviour for range. Notice that range uses recur to generate the integers without filling up memory (see the secion on recursion) as each new call to range overwrites the last one, however recur is not used when assembling the list of numbers, so if this list gets too big then that is when you get a JVM stack overflow (TODO: Check that this is correct) ([start end step] (lazy-seq (let [b (chunk-buffer 32) comp (if (pos? step) < >)] (loop [i start] (if (and (< (count b) 32) (comp i end)) (do (chunk-append b i) (recur (+ i step))) (chunk-cons (chunk b) (when (comp i end) (range i end step)))))))))

Errors

Understanding errors and finding bugs in your Clojure often depend on the information you recieve back from the Java Virtual Machine (JVM).

In the following example I have written a test suite that contains a few tests.

(deftest the-test-suite (testing “Simple tests” (is (= 1 1)) (is (= (+ 2 3) (add-me 2 3)))) (testing “Unicode Generation” (is (= nil (unicode-generator))) )

Unfortunately I made an error with the code. I didnt have paredit on and I missed off a closed bracket at the end. Its an easy mistake to make, although the error produced is not that helpful in diagnosing the problem.

Testing… Exception in thread “main” java.lang.RuntimeException: EOF while reading, starting at line 5, compiling:(simple_console/core_test.clj:12:1) at clojure.lang.Compiler.load(Compiler.java:7071) at clojure.lang.RT.loadResourceScript(RT.java:370) at clojure.lang.RT.loadResourceScript(RT.java:361) at clojure.lang.RT.load(RT.java:440) at clojure.lang.RT.load(RT.java:411) at clojure.core$load$fn__5018.invoke(core.clj:5530) at clojure.core$load.doInvoke(core.clj:5529) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.core$load_one.invoke(core.clj:5336) at clojure.core$load_lib$fn__4967.invoke(core.clj:5375) at clojure.core$load_lib.doInvoke(core.clj:5374) at clojure.lang.RestFn.applyTo(RestFn.java:142) at clojure.core$apply.invoke(core.clj:619) at clojure.core$load_libs.doInvoke(core.clj:5413) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invoke(core.clj:619) at clojure.core$require.doInvoke(core.clj:5496) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invoke(core.clj:619) at user$eval85.invoke(form-init3548849407380774503.clj:1) at clojure.lang.Compiler.eval(Compiler.java:6619) at clojure.lang.Compiler.eval(Compiler.java:6609) at clojure.lang.Compiler.load(Compiler.java:7064) at clojure.lang.Compiler.loadFile(Compiler.java:7020) at clojure.main$load_script.invoke(main.clj:294) at clojure.main$init_opt.invoke(main.clj:299) at clojure.main$initialize.invoke(main.clj:327) at clojure.main$null_opt.invoke(main.clj:362) at clojure.main$main.doInvoke(main.clj:440) at clojure.lang.RestFn.invoke(RestFn.java:421) at clojure.lang.Var.invoke(Var.java:419) at clojure.lang.AFn.applyToHelper(AFn.java:163) at clojure.lang.Var.applyTo(Var.java:532) at clojure.main.main(main.java:37) Caused by: java.lang.RuntimeException: EOF while reading, starting at line 5 at clojure.lang.Util.runtimeException(Util.java:219) at clojure.lang.LispReader.readDelimitedList(LispReader.java:1139) at clojure.lang.LispReader$ListReader.invoke(LispReader.java:982) at clojure.lang.LispReader.read(LispReader.java:185) at clojure.lang.Compiler.load(Compiler.java:7060) … 33 more Tests failed.

The End Of File exception was cased by trying to create the clojure code and at some point during the running of the code the Clojure code trips up because of the missing close bracket.

Asking questions in Clojure

Predicates (odd? 3) (even? 11)

Ask a question about every element in an arrays

(filter odd? [1 2 3 4 5 6 7 8 9])

Using Software Transactional Memory

overview

atoms

refs

changing state the Clojure way

swap!

Database access

Java Interoperability

Interesting articles and videos to read

Learing resources

Testing in Clojure

People write tests to support design discovery as well as manage the codebase changes over time.

In Clojure, many use the REPl to drive design discovery, so the need for tests to do that is potentially reduced. However, it is very powerful to codify the results of the discovery in tests as you are understanding the problem space. By creating code in the REPL, turning them into tests and then creating your code from those tests you are getting the best of both worlds.

Learning Overtone at Music Hack Day

Pre-requisits

Overtone requires a professional music library called Jack. If you really want to get the maximum performance out of overtone a real time kernel is recommended too.

mac

???

Ubuntu / Debian based systems

From the Overtone instructions it suggests adding the following packages sudo apt-get install jack-tools ant openjdk-6-jdk fftw3 qjackctl

On Ubuntu 13.04 fftw3 called libfftw3-3 and this was already installed on my laptop.

Earlier version is called fftw2, which was initially added and then removed when I realised that fftw2

Emacs with Clojure & Overtone

Emacs uses nrepl to start and connect to a Clojure REPL. Simply open a clojure file in the project you wish to run the REPL in and run the command nrepl-jack-in

M-x nrepl-jack-in

Keyboard combo: C-c C-j (this is one I configured myself)

The nrepl-jack-in command calls leiningen, which then runs and reads in the project configuration from the project.clj file. Once leiningen creates the REPL then Emacs opens a buffer window with the REPL prompt. You can now run Clojure code in this REPL buffer.

Starting Overtone

Although the REPL is running, you are not ready to use overtone just yet. First you need an overtone server.

You can use a local overtone server or the remote Overtone supercollider (assuming you have an Internet connection). We can tell the running REPL to use a local overtone server typing the following Clojure expression into the REPL buffer

(use ‘overtone.live)

Alternatively, if you open a Clojure file for your Overtone code and add (:use [overtone.live]) to the namespace then you can evaluate that Clojure file and it will start a local overtone server. To evaluate the Clojure file use the keyboard combo

C-c C-k

Evaluate all code

As you have just seen, you can evaluate all the code in a clojure file using the keyboard combo:

C-c C-k

So when you are writing your clojure code to drive Overtone, you can use this keyboard combo to load in any new or updated function or data definitions (defn and def expressions).

Evaluate code in-line

If you just make a simple change to your code then you can evaluate a single expression. Place the cursor at the end of the expression and use the command … or keyboard combo:

M-x .... C-x C-e

This will read and evaluate the expression and update the REPL runtime environment with any changes. So if you modify a def or defn expression, evaluating it makes it available to use.

If you just want to call a function you can also use this keyboard combo too. For example, if you have a function called foo, you can define an expression that calls it

(foo)

and then place your cursor at the end of that expression and use the C-x C-e combo to call the foo function and return any result (or side-effects).

changing the font face on emacs to make it all bigger, rather than just the text in buffers – TODO google this

6 months with clojure

I have spent the last 6 months on a project where Clojure was the main technology in use. I can’t really say much about the project itself, except that it’s a fairly complicated thing with lots of analytics and different kinds of data involved. We ended up with an environment that had a lot of Ruby and JavaScript/CoffeeScript as well as Clojure. We are using Neo4J for most of our data storage. In this blog post I wanted to basically talk about a few different things that has worked well or not so well with Clojure.

Being on 1.4

When the project started, Clojure 1.4 was in alpha. We still decided to run with it, so we were running Clojure 1.4alpha for about one month, and two different betas for another month or so. I have to say I was pleasently surprised - we only had one issue during this time (which had to do with toArray of records, when interacting with JRuby) - and that bug had already been fixed in trunk. The alphas and betas were exceptionally stable and upgrading to the final release of 1.4 didn’t really make any difference from a stack standpoint.

Compojure and Ring

We ended up using Compojure to build a fairly thin front end, with mostly JSON endpoints and serving up a few HTML pages that was the starting points for the JavaScript side of the app. In general, both Compojure and Ring works quite well - the ring server and the uberjar both worked with no major problems. I also like how clean and simple it is to create middleware for Ring. However, it was sometimes hard to find current documentation for Compojure - it seems it used to support many more things than it does right now, and most things people mention about it just aren’t true anymore.

Enlive

In order to get some dynamic things into our pages, we used Enlive. I really liked the model, and it was quite well suited for the restricted dynamicity we were after.

DSL with lots of data

One of my less bright ideas was to create an internal DSL for some of our data. The core part of the DSL was a bunch of macros that knew how to create domain objects of themselves. This ended up being very clean and a nice model to work with. However, since the data was in the amounts of millions of entries the slowness of actually evaluating that code (and compiling it, and dealing with the permgen issues) ended up getting unbearable. We recently moved to a model that is quite similar, except we don’t evalute the code, instead using read-string on the individual entries to parse them.

Dense functions

Clojure makes it really easy to create quite dense functions. I sometimes find myself combining five or six data structure manipulation functions in one go, then taking a step back and look at the whole thing. It usually makes sense the first time, but coming back to it later, or trying to explain what it does to a pair is usually quite complicated. Clojure has extraordinarily powerful functions for manipulation of data structures, and that makes it very easy to just chain them together into one big mess. So in order to be nice to my team mates (and myself) I force myself to break up those functions into smaller pieces.

Naming

One aspect of breaking up functions like described above, is that the operations involved are usually highly abstract and sometimes not very coupled to domain language. I find naming of those kind of functions very hard, and many times spend a long time and still not coming up with something I’m completely comfortable with. I don’t really have a solution to this problem right now.

Concurrency

For some reason, we haven’t used most of the concurrency aspects of Clojure at all. Maybe this is because our problems doesn’t suit themselves to concurrent processing, but I’m not sure this is the root of the reason. Suffice to say, most of our app is currently quite sequential. We will see if that changes going forward.

Summary

I’ve been having a blast with Clojure. It’s clearly the exactly right technology for what I’m currently doing, and it’s got a lot of features that makes it very convenient to use. I’m really looking forward being able to use it more going forward.

WIP

;; doall – dont be lazy, makes a lazy thing do what it does ;; pr-str – ???

;; Pretty Print - use instead of println ;; (pprint (for [x (range 10)] (range x)))

;; Clojure Naming convention - Kebab case ;; Taken from the idea of shish kebab, the naming convention in clojure uses hyphens between words use for namespaces, defs, defns, datastructures and ;; anything else a developer gives a name to in Clojure.

;; Clojurescript ;; Macros need to be compiled by Clojure rather than the Clojurescript compiler ;; so use the :require-macros

;; Stack overflow - how to tune the JVM for clojure - tweek your permgen - or use Java8

Things people struggled with the most (Stuart Sierra):

Working at the command-line. Even though we targeted professional programmers, some had never worked outside of an IDE and didn’t know shell basics like cd, ls, mkdir, etc.

Editing Clojure source code without a good editor. Dealing with the parentheses is easy in an editor with good paren-highlighting and paren-matching support; nearly impossible without. Some people even try to use Windows Notepad(!). At the other extreme, there’s always someone determined to learn Emacs at the same time as learning Clojure, which I don’t recommend.

Namespaces, files, and loading code. The subtleties of compile-time versus read-time versus load-time are hard even for experts to keep straight. The `ns`, `require`, and `import` forms are a mess of arbitrary rules, and countless examples on the web have different styles.

When to put parens around things. This surprised me at first, but a lot of students struggled with the difference between the value `foo` and the function call `(foo)`.

Debugging. How to understand a large function by breaking it into pieces and trying them at the REPL.

Java and the JVM.

Finding accurate and up-to-date documentation (most stuff on the web isn’t).

Finding and using libraries. The difference between Maven coordinates in `project.clj` and namespaces in Clojure source files.

Application design and architecture. One of the most common questions I get is “how do you organize your namespaces,” which always surprises me because it’s not something I think about much. But it definitely is a struggle for people who are used to class-oriented languages where much of the structure is enforced by the language.

Performace tips for clojure

http://www.fatvat.co.uk/2009/05/jvisualvm-and-clojure.html

(from Stack Exchange)

http://stackoverflow.com/users/214010/mikera

Check your algorithm first - are you incurring O(n^2) cost when it really should be O(n.log n)? If you’ve picked a bad algorithm, the rest of tuning is a waste of time. Be aware of common “gotchas” like the O(n) cost of traversing a list / sequence. Take advantage of nice features in Clojure, like the O(1) cost of copying a large persistent data structure or the O(log32 n) cost of map/set/vector accesses. Choose among Clojure’s core constructs wisely: An atom is great when you need some mutable data, e.g. updating some data in a loop If you are going to traverse some data in sequence, use a list rather than a vector or map since this will avoid creating temporary objects while traversing the sequence. Use deftype/defrecord/defprotocol where appropriate. These are heavily optimised, and in particular should be preferred to defstruct/multimethods as of Clojure 1.2 onwards. Take advantage of Clojure’s concurrency capabilities: pmap and future are both relatively easy ways to take advantage of multiple cores when you are doing a number of independent computations at the same time. Remember that because of Clojure’s immutable persistent data structures, making and working on multiple copies of data is very inexpensive. You also don’t have to worry about locking when taking snapshots..... If you are interfacing with Java code, use “(set! warn-on-reflection true)” and eliminate every reflection warning. Reflection is one of the most expensive operations, and will really slow your application down if done repeatedly. If you still need more performance, identify the most performance critical parts of your code (e.g. the 5% of lines where the application spends 90%+ of CPU time), analyse this section in detail and judiciously apply the following rules: Avoid laziness. Laziness is a great feature but comes with some additional overhead. Be aware that many of Clojure’s common sequence / list functions are lazy (e.g. for, map, partition). loop/recur, dotimes and reduce are your non-lazy friends. Use primitive hints and unchecked arithmetic to make arithmetic / numerical code faster. Primitives are much faster than Clojure’s default BigInteger arithmetic. Minimise memory allocations - try to avoid creating too much unnecessary intermediate data (vectors, lists, maps, non-primitive numbers etc.). All allocations impose a small amount of extra overhead, and also result in more/longer GC pauses over time (this is likely to be a bigger concern if you are writing a game / soft realtime app.). (Ab)use Java arrays - not really idiomatic in Clojure, but aget / aset / areduce and friends are very fast (they benefit from a lot of JVM optimisations!!). (Ab)use primitive arrays for extra bonus points. Use macros - to generate ugly-but-fast code at compile time where possible Doing all the above should get pretty good performance out of Clojure code - with careful tuning I’ve usually been able to get reasonably near to pure Java performance, which is pretty impressive for a dynamic language!

Require verses use

Clojure require vs. use

If you work in Clojure enough you’ll see both require and use near the top of files, indicating the external files and functions that are needed in that particular namespace.

Let’s say I want to use Ring’s wrap-params function.

(ns project.core (:require [project.player.player-controller :refer [routes-handler]]))

(def app-handler (-> routes-handler (wrap-params)))

(defn -main [] (run-jetty app-handler {:port 3000})) Let’s say I have a test suite and I run my tests. I get an error.

java.lang.RuntimeException: Unable to resolve symbol: wrap-params in this context

I get this error because I’m attempting to invoke a function defined in a third-party library, but this namespace has no idea where to find this function. It doesn’t know what wrap-params is.

Let’s add a line to our code.

(ns project.core (:require [project.player.player-controller :refer [routes-handler]]) (:use ring.middleware.params)) Now it works. But what’s happening? use is pulling in every single function from the ring.middleware.params library. It’s as if I had all those functions defined in this namespace. That’s far from ideal.

We could specify the functions we want to include with only.

(ns project.core (:require [project.player.player-controller :refer [routes-handler]]) (:use [ring.middleware.params :only [wrap-params]])) And it works!

But let’s take a couple steps back and adjust our original code a bit.

(ns project.core (:require [project.player.player-controller :refer [routes-handler]] [ring.middleware.params])) Same error as the first time! Why? require is slightly different than use. By requiring ring.middleware.params I’m giving myself access to that namespace. Hop down further in the code and make another change and we can have this working.

(def app-handler (-> routes-handler (ring.middleware.params/wrap-params))) Now it works! We specified the namespace where that function is defined. What if we did that from the beginning, but didn’t require that namespace?

java.lang.ClassNotFoundException: ring.middleware.params

It doesn’t know where to find ring.middleware.params. We can also alias the namespace to make this less verbose, yet potentially more clear.

(ns project.core (:require [project.player.player-controller :refer [routes-handler]] [ring.middleware.params :as ring]))

(def app-handler (-> routes-handler (ring/wrap-params))) That works! But for the most idiomatic solution, let’s use refer, which takes a vector of functions, those you wish to pull in.

(ns project.core (:require [project.player.player-controller :refer [routes-handler]] [ring.middleware.params :refer [wrap-params]))

(def app-handler (-> routes-handler (wrap-params))) Near the top of the file we specify the function (wrap-params) and location of the function (ring.middleware.params). This allows us to invoke the function just as we would any other function that we defined in this namespace.

So overall, what’s the difference between require - refer and use - only? Well, nothing really. require is more idiomatic, so it’s considered best practice to include external functions by providing the library to require and specifying the individual functions to include with refer. By themselves, require loads libraries and use loads libraries and refers to their namespaces (giving you everything, which is usually/always overkill). use can also easily lead to namespace conflicts (for the exact reason I just mentioned).

Lastly, and quickly, if you hop in the REPL, you have a few options for how you can make use of all of this.

(require ‘hyperion.api.set-ds! ‘hyperion.api.new-datastore) (require ‘(hyperion.api set-ds! new-datastore)) (require ‘[hyperion.api.set-ds! :as ds]) (require [‘hyperion.api.set-ds! :as ‘ds]) (use ‘[hyperion.api :only [new-datastore]]) All valid syntax, all behaves similarly.

Clojure: Destructuring

In The Joy of Clojure (TJoC) destructuring is described as a mini-language within Clojure. It’s not essential to learn this mini-language; however, as the authors of TJoC point out, destructuring facilitates concise, elegant code.

What is destructuring? Clojure supports abstract structural binding, often called destructuring, in let binding lists, fn parameter lists, and any macro that expands into a let or fn. – http://clojure.org/special_forms The simplest example of destructuring is assigning the values of a vector. user=> (def point [5 7]) #’user/point

user=> (let [[x y] point] (println “x:” x “y:” y)) x: 5 y: 7 note: I’m using let for my examples of destructuring; however, in practice I tend to use destructuring in function parameter lists at least as often, if not more often.

I’ll admit that I can’t remember ever using destructuring like the first example, but it’s a good starting point. A more realistic example is splitting a vector into a head and a tail. When defining a function with an arglist** you use an ampersand. The same is true in destructuring. user=> (def indexes [1 2 3]) #’user/indexes

user=> (let [[x & more] indexes] (println “x:” x “more:” more)) x: 1 more: (2 3) It’s also worth noting that you can bind the entire vector to a local using the :as directive. user=> (def indexes [1 2 3]) #’user/indexes

user=> (let [[x & more :as full-list] indexes] (println “x:” x “more:” more “full list:” full-list)) x: 1 more: (2 3) full list: [1 2 3] Vector examples are the easiest; however, in practice I find myself using destructuring with maps far more often.

Simple destructuring on a map is as easy as choosing a local name and providing the key. user=> (def point {:x 5 :y 7}) #’user/point

user=> (let [{the-x :x the-y :y} point] (println “x:” the-x “y:” the-y)) x: 5 y: 7 As the example shows, the values of :x and :y are bound to locals with the names the-x and the-y. In practice we would never prepend “the-” to our local names; however, using different names provides a bit of clarity for our first example. In production code you would be much more likely to want locals with the same name as the key. This works perfectly well, as the next example shows. user=> (def point {:x 5 :y 7}) #’user/point

user=> (let [{x :x y :y} point] (println “x:” x “y:” y)) x: 5 y: 7 While this works perfectly well, creating locals with the same name as the keys becomes tedious and annoying (especially when your keys are longer than one letter). Clojure anticipates this frustration and provides :keys directive that allows you to specify keys that you would like as locals with the same name. user=> (def point {:x 5 :y 7}) #’user/point

user=> (let [{:keys [x y]} point] (println “x:” x “y:” y)) x: 5 y: 7 There are a few directives that work while destructuring maps. The above example shows the use of :keys. In practice I end up using :keys the most; however, I’ve also used the :as directive while working with maps.

The following example illustrates the use of an :as directive to bind a local with the entire map. user=> (def point {:x 5 :y 7}) #’user/point

user=> (let [{:keys [x y] :as the-point} point] (println “x:” x “y:” y “point:” the-point)) x: 5 y: 7 point: {:x 5, :y 7} We’ve now seen the :as directive used for both vectors and maps. In both cases the local is always assigned to the entire expression that is being destructured.

For completeness I’ll document the :or directive; however, I must admit that I’ve never used it in practice. The :or directive is used to assign default values when the map being destructured doesn’t contain a specified key. user=> (def point {:y 7}) #’user/point

user=> (let [{:keys [x y] :or {x 0 y 0}} point] (println “x:” x “y:” y)) x: 0 y: 7 Lastly, it’s also worth noting that you can destructure nested maps, vectors and a combination of both.

The following example destructures a nested map user=> (def book {:name “SICP” :details {:pages 657 :isbn-10 “0262011530”}}) #’user/book

user=> (let [{name :name {pages :pages isbn-10 :isbn-10} :details} book] (println “name:” name “pages:” pages “isbn-10:” isbn-10)) name: SICP pages: 657 isbn-10: 0262011530 As you would expect, you can also use directives while destructuring nested maps. user=> (def book {:name “SICP” :details {:pages 657 :isbn-10 “0262011530”}}) #’user/book user=> user=> (let [{name :name {:keys [pages isbn-10]} :details} book] (println “name:” name “pages:” pages “isbn-10:” isbn-10)) name: SICP pages: 657 isbn-10: 0262011530 Destructuring nested vectors is also very straight-forward, as the following example illustrates user=> (def numbers 3 4) #’user/numbers

user=> (let [c d numbers] (println “a:” a “b:” b “c:” c “d:” d)) a: 1 b: 2 c: 3 d: 4 Since binding forms can be nested within one another arbitrarily, you can pull apart just about anything – http://clojure.org/special_forms The following example destructures a map and a vector at the same time. user=> (def golfer {:name “Jim” :scores [3 5 4 5]}) #’user/golfer

user=> (let [{name :name [hole1 hole2] :scores} golfer] (println “name:” name “hole1:” hole1 “hole2:” hole2)) name: Jim hole1: 3 hole2: 5 The same example can be rewritten using a function definition to show the simplicity of using destructuring in parameter lists. user=> (defn print-status [{name :name [hole1 hole2] :scores}] (println “name:” name “hole1:” hole1 “hole2:” hole2)) #’user/print-status

user=> (print-status {:name “Jim” :scores [3 5 4 5]}) name: Jim hole1: 3 hole2: 5 There are other (less used) directives and deeper explanations available on http://clojure.org/special_forms and in The Joy of Clojure. I recommend both.

**(defn do-something [x y & more] … )

Clojure Namespaces - NS CHEATSHEET

;; ;; * :require makes functions available with a namespace prefix. ;; ;; * :use makes functions available without a namespace prefix ;; (i.e., refers functions to the current namespace). ;; ;; * :import refers Java classes to the current namespace. ;; ;; * :refer-clojure affects availability of built-in (clojure.core) ;; functions. ;;

(ns foo.bar

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Refers clojure.contrib.math into current NS, e.g.: ;; (clojure.contrib.math/sqrt 4) [:require [clojure.contrib math]]

;; Refers math into current NS, e.g.: ;; (math/sqrt 4) [:require [clojure.contrib [math :as math]]]

;; Refers clojure.contrib.seq-utils and math into current NS, e.g.: ;; (clojure.contrib.seq-utils/flatten [[1 2] 3]) ;; (math/sqrt 4) [:require [clojure.contrib seq-utils [math :as math]]]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Refers all functions from clojure.contrib.math and ;; clojure.contrib.seq-utils into current NS, e.g.: ;; (sqrt 4) ;; (flatten [[1 2] 3]) [:use [clojure.contrib math seq-utils]]

;; Refers only sqrt and flatten into current NS, e.g.: ;; (sqrt 4) ;; (flatten [[1 2] 3]) [:use [clojure.contrib [math :only [sqrt]] [seq-utils :only [flatten]]]]

;; Refers all functions from clojure.contrib.math except sqrt into ;; current NS [:use [clojure.contrib.math :exclude [sqrt]]]

;; Refers sqrt into current NS as ccm-sqrt, plus all other math ;; functions e.g.: ;; (ccm-sqrt 4) ;; (round 1.3) [:use [clojure.contrib.math :rename {sqrt ccm-sqrt}]]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Refers ArrayList and HashMap into current NS: [:import [java.util ArrayList HashMap]]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Excludes built-in print [:refer-clojure :exclude [print]]

;; Excludes all built-ins except print [:refer-clojure :only [print]]

;; Renames built-in print to core-print [:refer-clojure :rename {print core-print}])

Clojure Card game

https://github.com/malcolmsparks/chordtrain https://github.com/andrewwhitehouse/pokertrain https://github.com/andrewwhitehouse/chordtrain http://stackoverflow.com/questions/15584553/clojure-delete-items-from-a-vector-to-represent-dealing-from-a-deck-of-cards http://iloveponies.github.io/120-hour-epic-sax-marathon/p-p-p-pokerface.html

To Read

http://iloveponies.github.io/120-hour-epic-sax-marathon/index.html http://iloveponies.github.io/120-hour-epic-sax-marathon/predicates.html http://iloveponies.github.io/120-hour-epic-sax-marathon/recursion.html http://iloveponies.github.io/120-hour-epic-sax-marathon/looping-is-recursion.html http://iloveponies.github.io/120-hour-epic-sax-marathon/one-function-to-rule-them-all.html http://clojure-is-love.herokuapp.com/ http://aphyr.com/posts/301-clojure-from-the-ground-up-welcome http://clojurekoans.com/

Repositories

https://github.com/jr0cket/rubyfuza2014

@weavejester

functional programming first releases september 2007 developed over 2 years

EDN - extensible data notaition

data description language

very similar to json

json has only 1 ordered collection type

edn has vector, list and set

Identifiers

json - string edn string - text data keyword - references itself symbol references something else

example {:name “Alice” :sex :femaile :job cryptographer}

sex value is assumed a universal definition that we dont need to reference exernally, however we may want to qualify the details of the job descrtiption

namespaces

:status/ready mamal.canine/dog

tags

#inst “<eg. timestamp>” #uuid “<eg. UUID>”

using tags helps us understand what the data represents. Some tags are built into edn, you can define your own too.

tags can have namespaces too

#color/rgb “e8df76”

Clojure = edn + eval

You can turn edn into a program by evaluating it, as clojure is a data driven language / syntax

symbols will evalutate to a bound value

pi evaluates to 3.144554504

(+ 1 1) evaluates to 2 (and true false) evalutes to false

LISP stands for list processing, clojure is a LISP, so all the lists are processed

evaluation

funtions evaluate their arguments first

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

macros

macros evalute their return value

(postfix (9 16 +))

homoniconic - treats code and data as equivical - the same representation

macros allo us to add new syntas through libraries core.async - async programming core.logic - logic programming core.typed - static typing - introducing a static typing support to a lanuguage that does not natively support that

Simple made easy

OO takes a defensive approach to manage complexity, i.e. encapsulation

clojure takes an offencsive approach

  • if something cannot change, it has zero complexity
  • immutable values cannot change, but they can represent change

mutible statte needed for – Performance – sharing state across threads

problem with encapsulation is that walls around objects are expensive as we have to write an api to use all of our objects

in distributed envrionemnts, we often work with immutable values - its an effecitve copy of the data between client and server

with immutable data structures in Clojure, you get an Api for free

  • getters
  • setters
  • transformations
  • diffing
  • traversal
  • serialisation

euality merging deceriilasition lensing auditing Concurrency

In clojure, instead of managing the complexity, we remove it

  • agressively trying to simplify