clojure made simple - lightning talk

Download Clojure made simple - Lightning talk

If you can't read please download the document

Upload: john-stevenson

Post on 16-Apr-2017

1.387 views

Category:

Technology


0 download

TRANSCRIPT

(simple (clojure))

Clojure made simple

Talk

What is Clojure

Clojure is small and flexible

Clojure concepts

Encourages Pure Functional approach - use STM to change state

Functions as first class citizens - functions as arguments as they return a value

Make JVM interoperation simple- easy to use your existing Java applications

Hickey's primary interest was concurrency he wanted the ability to write multi-threaded applications, but increasingly found the mutable, stateful paradigm of object oriented programming to be part of the problem

The idea of a functional Lisp integrated with a commercially accepted host platform just seemed like chocolate and peanut butter. Coming up with persistent data structures that were fast enough was the tipping point for my considering it viable.

functions as first-class objects, meaning that functions can be placed into data structures, passed as arguments to other functions, evaluated in comparisons, even returned as the return value of another function. Moreover, functions do not have "side effects" the ability to modify program state or data. This paradigm focuses on computation in the mathematical sense, rather than procedural algorithms, and is a completely different approach to programming.

Clojure does provide persistent data structures For application developers, the most significant distinction is that Clojure defaults to making all data structures immutable

developers must use one of four special mutable structures that are explicitly designed to be shared between threads: refs, vars, atoms, and agents. Clojure uses software transactional memory (STM) to coordinate changing these mutable structures while keeping them in a consistent state, much like a transactional database. This model makes it considerably simpler to write thread-safe code than it is in object oriented languages. No locks are required, therefore there are no deadlocks or race conditions.

A better Lisp !

Sensible () usage

Sensible macro names

JVM Interoperability

Clojure has a programmatic macro system which allows the compiler to be extended by user code

You can add your own language features with macros. Clojure itself is built out of macros such as defstruct:

(defstruct person :first-name :last-name)

If you need different semantics, write your own macro. If you want a variant of structs with strong typing and configurable null-checking for all fields, you can create your own defrecord macro, to be used like this:

(defrecord person [String :first-name String :last-name] :allow-nulls false)This ability to reprogram the language from within the language is the unique advantage of Lisp. You will see facets of this idea described in various ways: Lisp is homoiconic - Lisp code is just Lisp data. This makes it easy for programs to write other programs.The whole language is there, all the time. Paul Grahams essay Revenge of the Nerds explains why this is so powerful. http://www.paulgraham.com/icad.html

Lisp syntax also eliminates rules for operator precedence and associativity, with fully parenthesized expressions, there is no possible ambiguity

Which LISP is your wingman ?

Common Lisp

Clojure

The dark side of Clojure

( x )

The downside of Lisps simple, regular syntax, at least for beginners, is Lisps fixation on parentheses and on lists as the core data type. Clojure offers an interesting combination of features that makes Lisp more approachable for non-Lispers.

The dark side of Clojure

( ( x ) )

The downside of Lisps simple, regular syntax, at least for beginners, is Lisps fixation on parentheses and on lists as the core data type. Clojure offers an interesting combination of features that makes Lisp more approachable for non-Lispers.

The dark side of Clojure

( ( ( x ) ) )

The downside of Lisps simple, regular syntax, at least for beginners, is Lisps fixation on parentheses and on lists as the core data type. Clojure offers an interesting combination of features that makes Lisp more approachable for non-Lispers.

The dark side of Clojure

( ( ( ( x ) ) ) )

The downside of Lisps simple, regular syntax, at least for beginners, is Lisps fixation on parentheses and on lists as the core data type. Clojure offers an interesting combination of features that makes Lisp more approachable for non-Lispers.

The dark side of Clojure

( ( ( ( ( x ) ) ) ) )

The downside of Lisps simple, regular syntax, at least for beginners, is Lisps fixation on parentheses and on lists as the core data type. Clojure offers an interesting combination of features that makes Lisp more approachable for non-Lispers.

() == { () };

...verses non-lisp languages

([] ((()))) =={ ({([])}) };

Well nearly....

Comparing JavawithClojure

Its all byte code in the end..

Any object in clojure is just a regular java object

A reference type inheriting from:java.lang.object

BasicClojureSyntax

Name-spaces

; Define a namespace(ns name-space-name)

; Include namespace code(use 'names-space-name)

Groups code together like a package statement in Java

When you require a library named clojure.contrib.str-utils, Clojure looks fora file named clojure/contrib/str-utils.clj on the CLASSPATH

To avoid having to use the namespace for your library, you have to use refer, like so - (refer 'examples/introduction)

The use function does both require refer, like so (use 'examples.introduction)

o force a library to reload:(use :reload-all 'examples.introduction)

The :reload-all flag is useful if you are making changes and want to see results without restarting the REPL.

Defining a function

First principles(def name (fn [ args ] (function-body )))

Syntactic Sugar

(defn name [ args ] (function-body ...))

(defn welcome-message [ name ] (println (str Welcome to Clojure name))

(defn ) is syntactic sugar for (def name (function [] )

Most people use the defn shortcut as its much more readable.

Special forms

Special evaluation rules for the Clojure compiler - part of the language definition

catch, def, do, dot ('.'), finally, fn, if, let, loop, monitor-enter, monitor-exit, new, quote, recur, set!, throw, try and var

Simple function example

Define a simple function (defn hello-world [name] (println(str "Hello " name)))

Call the function in the REPL or in your code(hello-world "jr0cket")

Prefix notation

(defn square-the-number [x] (* x x))

Overloading functions

(defn make ([ ] ; do the following function if no args (struct vector 0 0) ) ([x y] ; do if x and y are arguments (struct vector x y) ) )

Immutable Data structures

List Ordered collection

(list 1 3 5 7)

'(1 3 5 7)

(1 2 3) ; 1 is not a function

Vectors hashed ordered list

[:matrix-characters [:neo :morpheus :trinity :smith]]

(first [:neo :morpheus :trinity :smith])

(nth [:matrix :babylon5 :firefly :stargate] 2)

(concat [:neo] [:trinity])

Maps unordered key/values

{:a 1 :b 2} {:a 1, :b 2}

{ :a 1 :b }java.lang.ArrayIndexOutOfBoundsException: 3

{ :a 1 :b 2} {:a 1, :b 2}

{:a {:a 1}} {:a {:a 1}}

{{:a 1} :a} {{:a 1} :a}; idiom - put :a on the left

Lists are for code

Vectors are for data

Working with data

(last [1 1 2 3 5 8])

(defn penultimate [x] (last (butlast x)) )

(penultimate [1 2 3 4 5])

(doc last)

(doc butlast)

And more...

(nth [1 1 2 3 5 8] 2)

(count [1 1 2 3 5 8])

(reverse [1 1 2 3 5 8])

(defn palindrome? [x] (= x (reverse x)) )

Proposition naming convention

Even more

(flatten [[1 1] 2 [3 [5 8]]])

(compress "aaaabccaadeeee")

(encode "aaaabccaadeeee")

(replicate 10 "a")

Defining a data structure

( def my-data-structure [ data ] )

( def days-of-the-week [Monday Tuesday Wednesday])

Example data structure

(def jr0cket {:first-name "John", :last-name "Stevenson"})

Get coding !

clojure.orgdocs.clojure.org

All hail the REPL

An interactive shell for clojure

Fast feedback loop for clojure

Managing a clojure project

Maven

Just like any other Java project

Step 1)Add Clojure library jar to your POM

Step 2)Download the Internet !!!

Leiningen

lein newlein depslein repllein swank

Create a new clojure project

Download all dependencies

Start the interactive shell (repl)

Start repl server

leiningen.org

Emacs

A few interesting Clojure examples

str

(str \h \e \l \l \o)

(def data boo)(str message data )

Concatenate strings togetherrepresent a character using \

Join arguments with strings

Ratio

Unique data type

Allow lazy evaluation

Avoid loss of precision

(/ 3 5)(/ 3.0 5)

(/ 1 3)(/ 1.0 3)

(class (/ 1 3)

Calling Java... ooooo!!

(javax.swing.JOptionPane/ showMessageDialog nil "Hello World" )

Importing Java into Clojure

(ns drawing-demo (:import [javax.swing Jpanel JFrame] [java.awt Dimension]))

Working with Java

Java Classes fullstop after class name(JFrame. )(Math/cos 3) ; static method call

Java methodsfullstop before method name(.getContentPane frame) ;;method name first(. frame getContentPane) ;;object first

What class is that...

(class (str "Jr0cket"))java.lang.String

(class (defn hello-world [name] (str "Hello cruel world")))clojure.lang.Var

Clojure calling Java web stuff

(let [conn] (doto (HttpUrlConnection. Url) (.setRequestMethod POST) (.setDoOutput true) (.setInstaneFollowRedirects true))])

Recursive functions

Functions that call themselves

Fractal coding

Tail recursion

Avoids blowing the stack

A trick as the JVM does not support tail recursion directly :-(

Tail recursion

(defn recursive-counter (print answer) (if (< answer 1000) (recur (+ answer 4))))

This is barfing because the evaluator has to keep around state for each call due to the expression (* x (factorial (- x 1))) . We need to make this function tail recursive.

recur can be thought of as the Clojure operator for looping. Think of it like a function call for the nearest enclosing let or function definition supplied with new variables. Naively we can switch over to using this by doing:

user> (defn factorial2 [x] (if (= x 0) 1 (* x (recur (- x 1)))))

But this is a compile-time error (which in itself is pretty neat!).java.lang.UnsupportedOperationException: Can only recur from tail position (NO_SOURCE_FILE:4)

An accumulator parameter is an extra parameter to a function that's used to gather intermediate parts of the calculation. If we do this, we can make sure that the recur call is in the tail position. Using an anonymous function we get:

(defn factorial3 [x] ((fn [x y] (if (= x 0) y (recur (- x 1) (* x y)))) x 1))

Now when recur is used, it doesn't need to keep any of the previous stack frame around. This means we can finally calculate factorial 1000000, which begins with 282 and ends with lots of zeros!

Where to find out more...

clojure.org/cheatsheet

Mutable State

Software Transactional Memory

Provides safe, concurrent access to memory

Agents allow encapsulated access to mutable resources

Functional for the web

Big blog of stuff in > Big blob of stuff out

Encourages modularising responsibilities

Good at processing data in parallel

Noir webnoir.org

Hiccuplibrary for representing HTML in Clojure. It uses vectors to represent tags, and maps to represent a tag's attributes.

More to come...

clojure.org dev.clojure.org

@jr0cketclojure.jr0cket.co.uk

Muokkaa otsikon tekstimuotoa napsauttamalla

Muokkaa jsennyksen tekstimuotoa napsauttamallaToinen jsennystasoKolmas jsennystasoNeljs jsennystasoViides jsennystasoKuudes jsennystasoSeitsems jsennystasoKahdeksas jsennystasoYhdekss jsennystaso