There and Back Again

114
There and Back Again: a developers travels in the land of Clojure Mike Harris

Transcript of There and Back Again

There and Back Again: a developers travels in the land of Clojure

Mike Harris

Travel Log• Equipment

• Higher Order Functions

• Variadic Functions with Splat / Apply

• Destructuring

• Map Structure

— J.R.R. Tolkien, The Lord of the Rings

“It's a dangerous business, Frodo, going out your door. You step onto the road, and if you

don't keep your feet, there's no knowing where you might be swept off to.”

Travel Log• Equipment

• Higher Order Functions

• Variadic Functions with Splat / Apply

• Destructuring

• Map Structure

ECMAScript 6

• Nodev0.12.2

• Babel5.1.13

lodash

• Nodev0.12.2

• lodash3.7.0

Clojure

• Clojure1.6.0

JS

var should = require('should'); var companySize = function() {return 15;}; companySize().should.equal(15);

JS

import * as should from 'should' let companySize = () => 15;companySize().should.equal(15);

ES 6

(() => 15)().should.equal(15);

ES 6

(ns presentation.example (require [clojure.test :refer :all])) (is (= 4 (+ 2 2)))

(defn companySize [] 15) (is (= 15 (companySize)))

(is (= 15 ((fn [] 15))))

Travel Log• Equipment

• Higher Order Functions

• Variadic Functions with Splat / Apply

• Destructuring

• Map Structure

— Alan J. Perlis, Epigrams on Programming, #5

“If a program manipulates a large amount of data, it does so in a small number of ways.”

function A

Produces

function B

JS

var a = function() { return function b() { return 'Bilbo'; };};a()().should.equal(‘Bilbo');

JS

let a = () => () => ‘Bilbo';a()().should.equal(‘Bilbo');

ES 6

(defn a [] (fn b [] "Bilbo"))(is (= "Bilbo" ((a))))

function A

Consum

es

function B

JS

var a = function(b) { return b();};a(function b() { return 'Bilbo'; }).should.equal(‘Bilbo');

JS

let a = (b) => b();a(() => 'Bilbo') .should.equal('Bilbo')

ES 6

(defn a [b] (b))(is (= "Bilbo" (a (fn b [] "Bilbo"))))

dwarfdwarfdwarf name gender

Plucked

name

name

JS

let dwarves = [{name: "Ori", gender: "Male"}, {name: "Dori", gender: "Male"}, {name: "Nori", gender: “Male”}];_.pluck(dwarves, 'name') .should.eql(['Ori', 'Dori', 'Nori'])

ES 6

(def dwarves [{:name "Ori" :gender “Male"} {:name "Dori" :gender "Male"} {:name "Nori" :gender “Male"}])

(is (= ["Ori" "Dori" "Nori"] (map :name dwarves)))

1 2

Reduce

3 4

10

+ 0

JS

_.reduce( [1, 2, 3, 4], (m, x) => m + x, 0) .should.equal(10)

ES 6

_.reduce( [1, 2, 3, 4], (m, x) => m + x) .should.equal(10)

ES 6

_.reduce( [1, 2, 3, 4], (m, x) => m + x, 100) .should.equal(110)

ES 6

(is (= 10 (reduce + 0 [1 2 3 4])))

(is (= 10 (reduce + [1 2 3 4])))

(is (= 110 (reduce + 100 [1 2 3 4])))

Travel Log• Equipment

• Higher Order Functions

• Variadic Functions with Splat / Apply

• Destructuring

• Map Structure

— J.R.R. Tolkien, The Hobbit

“‘Go back?’ he thought. ‘No good at all! Go sideways? Impossible! Go forward? Only thing

to do! On we go!’”

summer values …

Splat

summer 1 2 3 4 5 6

JS

function summer() { return _.reduce( Array.prototype.slice.call( arguments, summer.length), function(m, x) { return m + x; }, 0);};summer( 1, 2, 3, 4, 5, 6).should.equal(21);

summer(1, 2).should.equal(3); summer().should.equal(0); summer(8).should.equal(8);

let summer = (...values) => _.reduce( values, (m, x) => m + x, 0); summer( 1, 2, 3, 4, 5, 6).should.equal(21);

ES 6

summer(1, 2).should.equal(3); summer().should.equal(0); summer(8).should.equal(8);

ES 6

(defn summer [& values] (apply + values))(is (= 21 (summer 1 2 3 4 5 6)))

(is (= 3 (summer 1 2))) (is (= 0 (summer)))(is (= 8 (summer 8)))

(is (= 21 (+ 1 2 3 4 5 6)))

(is (= 3 (+ 1 2)))

summer is built into Clojure as +

(is (= 0 (+)))(is (= 8 (+ 8)))

summer is built into Clojure as +

Travel Log• Equipment

• Higher Order Functions

• Variadic Functions with Splat / Apply

• Destructuring

• Map Structure

— J.R.R. Tolkien, The Hobbit

“Escaping goblins to be caught by wolves!”

hobbit name age

Destructured

name family

family pasttime

JS

let [a, ,c] = [1, 2, 3, 4, 5]; a.should.equal(1);c.should.equal(3);

ES 6

let [a=0, ,c, ,e=99] = [1, 2]; a.should.equal(1);should(c).be.equal(undefined);e.should.equal(99);

ES 6

let bilbo = { name: ‘Bilbo', age: 50, family: ['Baggins', 'Took'], pastTime: ['writing']}; let {name, family:parents} = bilbo;

ES 6

name.should.equal(‘Bilbo');parents.should.eql( ['Baggins', ‘Took']);

ES 6

let hobbies = ({name, pastTime:hobbies}) => name + ' enjoys ' + hobbies.join(‘,');

ES 6

hobbies(bilbo).should .equal('Bilbo enjoys writing’); hobbies( {name: ‘Gollum', something: ‘else’ pastTime:[‘precious!']}) .should.equal( 'Gollum enjoys precious!');

ES 6

(def values [1 2 3 4 5]) (let [[a _ c] values] (is (= a 1)) (is (= c 3)))

(def values [1 2 3 4 5])(let [[a _ & xs] values] (is (= a 1)) (is (= [3 4 5] xs)))

(def bilbo {:name "Bilbo" :age 50 :family ["Baggins" "Took"] :past-time ["writing"]})

(let [{name :name parents :family} bilbo] (is (= "Bilbo" name)) (is (= ["Baggins" "Took"] parents))

(defn hobbies [{ name :name hobbies :past-time}] (str name " enjoys " (clojure.string/join ", " hobbies)))

(is (= "Bilbo enjoys writing" (hobbies bilbo)))(is (= "Gollum enjoys precious!" (hobbies {:name “Gollum" :something “else” :past-time ["precious!"]})))

Travel Log• Equipment

• Higher Order Functions

• Variadic Functions with Splat / Apply

• Destructuring

• Map Structure

— Alan J. Perlis, Epigrams on Programming, #9

“It is better to have 100 functions operate on one data structure than 10 functions on 10 data

structures.”

hobbit name age

Made up of

family pasttime

name age family pasttime

JS

var bilbo = { name: 'Bilbo', age: 50, family: ['Baggins', ‘Took'], pastTime: ['writing']};

_.pick(bilbo, 'name') .should.eql({name: ‘Bilbo'});_.pick(bilbo, ['name', 'family']) .should.eql( {name: 'Bilbo', family: ['Baggins', ‘Took']}); _.pick(bilbo, ‘none').should.eql({});

_.get(bilbo, 'name') .should.equal(‘Bilbo');_.get(bilbo, 'none', 'not found') .should.equal('not found’);should(_.get(bilbo, 'none')) .equal(undefined);

(def bilbo {:name "Bilbo" :age 50 :family ["Baggins" "Took"] :past-time ["writing"]})

(is (= "Bilbo" (:name bilbo))) (is (= "Bilbo" (bilbo :name))) (is (= "Bilbo" (get bilbo :name)))

(is (= nil (get bilbo :none))) (is (= :not-found (get bilbo :none :not-found))) (is (= nil (bilbo :none))) (is (= nil (:none bilbo)))

(is (= {:name "Bilbo"} (select-keys bilbo [:name])))

(is (= {:name "Bilbo" :family ["Baggins" "Took"]} (select-keys bilbo [:name :family])))

(is (= {} (select-keys bilbo [:none]))) (is (= {:name "Bilbo"} (select-keys bilbo [:name :none])))

A B

Com

bined

A B

A C

C

JS

_.assign( {a: 1, b: 1}, {a: 2, c: 2}) .should.eql({a: 2, b: 1, c: 2});

_.merge( {a: 1, b: 1}, {a: 2, c: 2}) .should.eql({a: 2, b: 1, c: 2});

_.assign( {a: {x: 1}, b: 1}, {a: {y: 2}, c: 2}) .should.eql( {a: {y: 2}, b: 1, c: 2});

_.merge( {a: {x: 1}, b: 1}, {a: {y: 2}, c: 2}) .should.eql( {a: {x: 1, y: 2}, b: 1, c: 2});

(is (= {:a 2 :b 1 :c 2} (merge {:a 1 :b 1} {:a 2 :c 2})))

(is (= {:a {:y 2} :b 1 :c 2} (merge {:a {:x 1} :b 1} {:a {:y 2} :c 2})))

(is (= {:a {:x 1 :y 2} :b 1 :c 2} (merge-with conj {:a {:x 1} :b 1} {:a {:y 2} :c 2})))

— J.R.R. Tolkien, The Hobbit

“As all things come to an end, even this story.”

Travel Log• Equipment

• Higher Order Functions

• Variadic Functions with Splat / Apply

• Destructuring

• Map Structure

Thank you!

Mike Harris@MikeMKHhttp://comp-phil.blogspot.com/

— J.R.R. Tolkien, The Hobbit

“May the wind under your wings bear you where the sun sails and the moon walks.”

Bibliography(conference session)

• “Simple Made Easy” by Rich Hickey at Strange Loop 2011 http://www.infoq.com/presentations/Simple-Made-Easy

• “Coder Decoder: Functional Programming Lingo Explained, with Pictures” by Katie Miller at Strange Loop 2014 https://www.youtube.com/watch?v=uwrCQmpZ8Ts

• “Pattern Matching in Clojure” by Sean Johnson at Clojure/West 2015 https://www.youtube.com/watch?v=n7aE6k8o_BU

Bibliography(egghead.io videos)

• “Asynchronous Programming: The End of Loop” by Jafar Husain https://egghead.io/series/mastering-asynchronous-programming-the-end-of-the-loop

• “Introduction to Lodash” by John Lindquist https://egghead.io/lessons/core-javascript-introduction-to-lodash

• “Lodash: Refactoring Simple For Loops” by John Lindquist https://egghead.io/lessons/javascript-lodash-refactoring-simple-for-loops

• “ECMAscript6” by John Lindquist https://egghead.io/technologies/es6

Bibliography(Clojure books)

• “The Joy of Clojure” by Michael Fogus and Chris Houser

• “Programming Clojure” by Stuart Halloway and Aaron Bedra

• “Clojure Programming” by Chas Emerick, Brian Carper, and Christophe Grand

Bibliography(Functional JavaScript books)

• “Functional JavaScript: Introducing Functional Programming with Underscore.js” by Michael Fogus

• “JavaScript Allongé” by Reginald Braithwaite https://leanpub.com/javascript-allonge

Image Sources• The Hobbit book covers from http://commons.wikimedia.org/wiki/File:HMCoSecondEdHobbits.jpg

• Socrates take by Eric Gaba from http://en.wikipedia.org/wiki/File:Socrates_Louvre.jpg

• The Divided Line created by Neal Burton from http://outre-monde.com/2010/09/25/platonic-myths-the-sun-line-and-cave/

• The Hobbit images* are by Mikhail Belomlinsky from http://viola.bz/the-first-illustrator-of-the-hobbit/

• Babel from https://github.com/babel/babel

• Lodash from https://github.com/lodash/lodash

• Clojure from http://clojure.org/

• The Hobbit image (wolves)* by Tove Jansson from http://www.tolkien.com.pl/hobbit/collection/hobbit-swedish-1962.php

• Me taken by Kelsey Harris at Strange Loop 2014