Clojure for OOP folks Stefan innoq

Similar documents
Clojure: Enemy of the State

Java, with a Clojure

Clojure is. A dynamic, LISP-based. programming language. running on the JVM

Macro #clojureconj

Symbols. abstractions, implementing, 270 through indirection, 77 with macros, 183 abstract syntax tree (AST), 149

Clojure Lisp for the Real clojure.com

What if Type Systems were more like Linters?

Clojure. A (not-so-pure) functional approach to concurrency. Paolo Baldan Linguaggi per il Global Computing AA 2016/2017

This tutorial is designed for all those software professionals who are keen on learning the basics of Clojure and how to put it into practice.

One size does not fit all

7 Topics Concerning Languages & Architecture Stefan JUG KA 2011

REST: I don't Think it Means What You Think it Does. Stefan

CPL 2016, week 10. Clojure functional core. Oleg Batrashev. April 11, Institute of Computer Science, Tartu, Estonia

Rascal Tutorial. Tijs van der Storm Wednesday, May 23, 12

June 27, 2014 EuroClojure 2014 Krakow, Poland. Components. Just Enough

Clojure Concurrency Constructs. CSCI 5828: Foundations of Software Engineering Lecture 12 10/02/2014

Introduction Basics Concurrency Conclusion. Clojure. Marcel Klinzing. December 13, M. Klinzing Clojure 1/18

Building Flexible Systems

Stuart

The Curious Clojureist

Seminar on Languages for Scientific Computing Aachen, 6 Feb Navid Abbaszadeh.

Michiel DomCode, May 26th 2015

Reagent. a ClojureScript interface to React. React Amsterdam Meetup 12 Feb. 2015

Clojure. A Dynamic Programming Language for the JVM. Rich Hickey

ClojureScript. as a compilation target to JS. Michiel Vijay FP AMS October 16th 2014

.consulting.solutions.partnership. Clojure by Example. A practical introduction to Clojure on the JVM

Clojure Distilled. Immutable

Michael Fogus Chris Houser FOREWORD BY STEVE YEGGE MANNING

POETRY OF PROGRAMMING CODE READING EXERCISES IN CLOJURE V

Clojure. A Dynamic Programming Language for the JVM. (and CLR) Rich Hickey

Java9 - Features abseits von Jigsaw und JShell. BED-Con September 2017

Vectors in Scheme. Data Structures in Scheme

Clojure Lisp for the Real #clojure

Lecture 16: Object Programming Languages

Blockchain (a.k.a. the slowest, most fascinating database you ll ever see)

G Programming Languages - Fall 2012

Data Structures in Functional Languages

BUILDING DECLARATIVE GUIS WITH CLOJURE, JAVAFX AND FN-FX DR. NILS BLUM-OESTE

Lazytest Better Living Through Protocols. Stuart Sierra. Clojure NYC April 15, 2010

Microservices. Are your Frameworks ready? Martin Eigenbrodt Alexander Heusingfeld

Programming Clojure, Third Edition

Tool-assisted spec development

Multi-core Parallelization in Clojure - a Case Study

Table of Contents. Preface... xxi

Day 3. COMP 1006/1406A Summer M. Jason Hinek Carleton University

OBJECT ORIENTED PROGRAMMING

Java Object Oriented Design. CSC207 Fall 2014

Making New instances of Classes

Clojure & Incanter for Java Programmers

Introduction to Programming (Java) 4/12

ITI Introduction to Computing II

1.3.4 case and case* macro since 1.2. Listing Conditional Branching, Fast Switch. Listing Contract

JavaScript. History. Adding JavaScript to a page. CS144: Web Applications

Persistent Data Structures and Managed References

Programming Languages

CS108, Stanford Handout #3. HW1 CodeCamp

PROGRAMMING LANGUAGE 2

Inheritance. OOP: Inheritance 1

Scala : an LLVM-targeted Scala compiler

ITI Introduction to Computing II

Object Oriented Programming (OOP)

Identity, State and Values

Why Prismatic Goes Faster With Clojure

Java Programming. U Hou Lok. Java Aug., Department of Computer Science and Information Engineering, National Taiwan University

Introduction to Spark

Principles of Programming Languages

CS Programming Languages: Scala

G Programming Languages Spring 2010 Lecture 9. Robert Grimm, New York University

Programming Languages and Techniques (CIS120)

clojure & cfml sitting in a tree sean corfield world singles

Life in a Post-Functional World

Token Interception for Syntax Embedding

What s different about Factor?

Behind the scenes - Continuous log analytics

PERSISTENT SEQUENCES WITH EFFECTIVE RANDOM ACCESS AND SUPPORT FOR INFINITY

Chapter 10 Classes Continued. Fundamentals of Java

Programming Clojure. Extracted from: Second Edition. The Pragmatic Bookshelf

Method Slots: Supporting Methods, Events, and Advices by a Single Language Construct

From Java to C++ From Java to C++ CSE250 Lecture Notes Weeks 1 2, part of 3. Kenneth W. Regan University at Buffalo (SUNY) September 10, 2009

A Practical Optional Type System for Clojure. Ambrose Bonnaire-Sergeant

Clojure philosophy. This chapter covers. The Clojure way Why a(nother) Lisp? Functional programming Why Clojure isn t especially object-oriented

Programming Languages. Function-Closure Idioms. Adapted from Dan Grossman's PL class, U. of Washington

Inheritance and Substitution (Budd chapter 8, 10)

1. Write two major differences between Object-oriented programming and procedural programming?

Programming by Delegation

Introduction to Clojure Concurrency (and data structures)

Functional Programming. Pure Functional Programming

COURSE 2 DESIGN PATTERNS

Functional programming is a productive

Inheritance and Polymorphism

Object-Oriented Design

Declarative concurrency. March 3, 2014

G Programming Languages - Fall 2012

Object-Relational Mapping

Use of Clojure in Undergraduate CS Curriculum

Introduction to Typed Racket. The plan: Racket Crash Course Typed Racket and PL Racket Differences with the text Some PL Racket Examples

Inheritance. Finally, the final keyword. A widely example using inheritance. OOP: Inheritance 1

Csci 102: Sample Exam

Bridge Pattern. Used to decouple an abstraction from its implementation so that the two can vary independently

Intermediate Code, Object Representation, Type-Based Optimization

Transcription:

Clojure for OOP folks Stefan Tilkov @stilkov innoq 1

Motivation 2

Syntax Idioms 3

OOP Thinking model domains with classes & interfaces encapsulate data in objects prefer specific over generic solutions explicitly provide for generic access 4

Namespaces 5

... just like Java packages 6

refer: import names :exclude [], :only [], :rename { : } Handle var name clashes Reduce dependencies require: (re-)load libs :reload, :reload-all, :as Dynamic reloading Namespace aliases use: require + refer :exclude [], :only [], :rename { : } Convenient REPL usage ns: create namespace :require, :refer, :use, :gen-class Flexible handling in sources Provide encapsulation 7

refer: import names :exclude [], :only [], :rename { : } Handle var name clashes Reduce dependencies require: (re-)load libs :reload, :reload-all, :as, :refer Dynamic reloading Namespace aliases Convenient REPL usage ns: create namespace :require, :refer, :use, :gen-class Flexible handling in sources Provide encapsulation 8

(ns com.example.some-ns "Well-documented ns" (:use [com.example.n1 :only [xyz]]) (:require [com.example.ns2 :as n2])) (defn...) (defmacro...) (defmulti...) (defmethod...) (defn-...) (def ^:private...) (def ^:dynamic...) 9

Data 10

How to choose a datatype 11

https://github.com/cemerick/clojure-type-selection-flowchart/ 2011 Chas Emerick, cemerick.com 12

Map Record Type https://github.com/cemerick/clojure-type-selection-flowchart/ 2011 Chas Emerick, cemerick.com 13

Map Function Record Multimethod Type Protocol 14

Map Function Multimethod 15

Map Function 16

PDS Function 17

Data structures vs. objects public class Point { private final double x; private final double y; (def p1 [3 4]) } public Point(double x, double y) { this.x = x; this.y = y; } Point p1 = new Point(3, 4); 18

Data structures vs. objects (def p1 [3 4]) Immutable Reusable Compatible 19

Data structures vs. objects import static java.lang.math.sqrt; public class Point { private final double x; private final double y; public Point(double x, double y) { } this.x = x; this.y = y; } public double distanceto(point other) { double c1 = other.x - this.x; } double c2 = other.y - this.y; return sqrt(c1 * c1 + c2 * c2); 20

Data structures vs. objects (import-static java.lang.math sqrt) (defn distance [[x1 y1] [x2 y2]] (let [c1 (- x2 x1) c2 (- y2 y1)] (sqrt (+ (* c1 c1) (* c2 c2))))) 21

Data structures vs. objects (defn rand-seq [limit] (repeatedly #(rand-int limit))) infinite randoms (take 10 (partition 2 (rand-seq 10))) pairs of random ints 10 random points ;((3 6) (6 1) (8 5) (0 7) (3 8) (0 6) (1 6) (7 6) (0 1) (8 9)) 22

Data structures vs. objects (defn circumference [vertices] (reduce + (map distance vertices (drop 1 (cycle vertices))))) infinite repetition all seq without first ;((3 6) (6 1) (8 5) (0 7) (3 8) (0 6) (1 6) (7 6) (0 1) (8 9))... ;((6 1) (8 5) (0 7) (3 8) (0 6) (1 6) (7 6) (0 1) (8 9) (3 6)) ;58.06411369758525 23

assoc assoc-in butlast concat conj cons count cycle difference dissoc distinct distinct? drop-last empty empty? every? filter first flatten group-by interleave interpose intersection into join lazy-cat mapcat merge merge-with not-any? not-empty? not-every? nth partition partition-all partition-by peek pop popy project remove replace rest rseq select select-keys shuffle some split-at split-with subvec take take-last take-nth take-while union update-in 24

Maps (def projects #{{:id "1", :kind :time-material, :description "Consulting for BigCo", :budget 25000, :team [:joe, :chuck, :james]} {:id "2", :kind :fixed-price, :description "Development for Startup", :budget 100000, :team [:john, :chuck, :james, :bill]} {:id "3", :kind :fixed-price, :description "Clojure Training", :budget 3000, :team [:joe, :john]}}) 25

Map access (defn all-members [projects] (reduce conj #{} (flatten (map :team projects)))) seq of vectors seq of members with duplicates set of all team members (all-members projects) ;#{:chuck :joe :james :john :bill} 26

Map access & coupling (defn all-members [projects] (reduce conj #{} (flatten (map :team projects)))) #{{:id "2", :kind :fixed-price, :description "Development for Startup", :budget 100000, :team [:john, :chuck, :james, :bill]}} 27

Map access & coupling (defn all-members [projects] (reduce conj #{} (flatten (map :team projects)))) #{{:id "2", :kind :fixed-price, :description "Development for Startup", :budget 100000, :team [:john, :chuck, :james, :bill]}} 28

(json-str) [{:kind "fixed-price", :team ["john" "chuck" "james" "bill"], :budget 100000, :id "2", :description "Development for Startup"} {:kind "fixed-price", :team ["joe" "john"], :budget 3000, :id "3", :description "Clojure Training"} {:kind "time-material", :team ["joe" "chuck" "james"], :budget 25000, :id "1", :description "Consulting for BigCo"}] [{"kind":"fixed-price", "team":["john", "chuck", "james", "bill"], "budget":100000, "id":"2", "description":"development for Startup"}, {"kind":"fixed-price", "team":["joe", "john"], "budget":3000, "id":"3", "description":"clojure Training"}, {"kind":"time-material", "team":["joe", "chuck", "james"], "budget":25000, "id":"1", "description":"consulting for BigCo"}] (read-json) 29

(ns com.example.some-ns "Well-documented ns" (:use [com.example.n1 :only [xyz]]) (:require [com.example.ns2 :as n2])) (defn...) (defmacro...) (defmulti...) (defmethod...) (defn-...) (def ^:private...) 30

Interface Implementation Functions w/ simple data 31

Closures 2011 innoq Deutschland GmbH 32

(defn make-id [prefix id] (join "-" [prefix (Long/toString id 16)])) (defn id-generator ([prefix] (id-generator prefix 0)) ([prefix v] (let [cnt (atom v)] (fn [] (make-id prefix (swap! cnt inc)))))) (def prj-id (id-generator "prj")) (prj-id) ;; "prj-1" (prj-id) ;; "prj-2" (prj-id) ;; "prj-3" (defn make-project [map] (assoc map :id (prj-id))) 2011 innoq Deutschland GmbH 33

Meet Miss Grant http://www.informit.com/articles/article.aspx?p=1592379 34

(defn unlock-door [] (println "Unlocking door")) (defn lock-door [] (println "Locking door")) (defn unlock-panel [] (println "Unlocking panel")) (defn lock-panel [] (println "Locking panel")) (def fsm (make-fsm :idle :dooropened {:idle [[unlock-door lock-panel] {:doorclosed :active}] :active [[] {:draweropened :waitingforlight :lighton :waitingfordrawer}] :waitingforlight [[] {:lighton :unlockedpanel}] :waitingfordrawer [[] {:draweropened :unlockedpanel}] :unlockedpanel [[unlock-panel lock-door] {:panelclosed :idle}]})) 35

(defn make-fsm "creates an fsm with initial state s0, a reset event, and a map of transitions. [state-transitions] must be a map of state->[[f1 f2...] {e0->s0, e1->s2,...}]" [s0 reset-event state-transitions ] (let [s (atom s0)] (fn [evt] (if (= evt reset-event) (do (println "Reset event, returning to " s0) (swap! s (fn [_] s0))) (let [[actions transitions] (state-transitions @s)] (if-let [new-state (transitions evt)] (do (println "Event" evt "causes transition from" @s "to" new-state) (doseq [f actions] (f)) (swap! s (fn [_] new-state))) (println "Unexpected/unhandled event" evt "in state" @s))))))) 2011 innoq Deutschland GmbH 36

(def fsm (make-fsm :idle :dooropened {:idle [[unlock-door lock-panel] {:doorclosed :active}] :active [[] {:draweropened :waitingforlight :lighton :waitingfordrawer}] :waitingforlight [[] {:lighton :unlockedpanel}] :waitingfordrawer [[] {:draweropened :unlockedpanel}] :unlockedpanel [[unlock-panel lock-door] {:panelclosed :idle}]})) (dorun (map fsm [:doorclosed :lighton :drawopened :panelclosed])) ;; Event :doorclosed causes transition from :idle to :active ;; Unlocking door ;; Locking panel ;; Event :lighton causes transition from :active to :waitingfordrawer ;; Event :draweropened causes transition from :waitingfordrawer to :unlockedpanel ;; Event :panelclosed causes transition from :unlockedpanel to :idle ;; Unlocking panel ;; Locking door ;; Reset event, returning to :idle 2011 innoq Deutschland GmbH 37

Map Function Multimethod 38

Method problems Global state Coarse-grained re-use Simple-minded dispatch 39

Methods vs. Multimethods Methods Multimethods Dispatch Type customizable # of args 1 arbitrary Hierarchy based on type inheritance customizable 40

Multimethods (def projects #{{:id "1", :kind :time-material, :description "Consulting for BigCo", :budget 25000, :team [:joe, :chuck, :james]} {:id "2", :kind :fixed-price, :description "Development for Startup", :budget 100000, :team [:john, :chuck, :james, :bill]} {:id "3", :kind :fixed-price, :description "Clojure Training", :budget 3000, :team [:joe, :john]}}) 41

Multimethods (defmulti expected-revenue :kind) (defmethod expected-revenue :default [p] (:budget p)) (defmethod expected-revenue :fixed-price [p] (* 0.8 (:budget p))) (defn total-expected-revenue [projects] (reduce + (map expected-revenue projects))) 42

Multimethods (defn make-rectangle [[p1 p2 p3 p4 :as vertices]] (let [a (distance p1 p2) b (distance p2 p3)] (assert (= a (distance p3 p4))) (assert (= b (distance p4 p1))) {:kind :rectangle, :vertices vertices, :a a, :b b})) (defn make-circle [center r] {:kind :circle, :center center, :r r}) (defmulti area :kind) (defmethod area :rectangle [{:keys [a b]}] (* a b)) (defmethod area :circle [{:keys [r]}] (* PI (pow r 2))) 43

Multimethods (defmulti circumference :kind :default :polygon) (defmethod circumference :polygon [{:keys [vertices]}] (reduce + (map distance vertices (drop 1 (cycle vertices))))) (defmethod circumference :rectangle [{:keys [a b]}] (* 2 (+ a b))) 44

Multimethods (defmulti draw-shape (fn [shape canvas] [(:kind shape) (:type canvas)])) (defmethod draw-shape :default [shape canvas] (str "Drawing " (:kind shape) " on " (:type canvas))) (defmethod draw-shape [:circle :print-canvas] [shape canvas] "Printing a circle") (defmethod draw-shape [:rectangle :display-canvas] [shape canvas] "Showing a rectangle") 45

defrecord, deftype 2011 innoq Deutschland GmbH 46

Map Function Record Multimethod Type Protocol 47

defrecord Supports map access Flexible & extensible No structural sharing Code overhead Convenience functions Better performance Platform integration Protocol support 48

deftype No generic overhead Convenience functions Best performance Platform integration No structural sharing No map access Static & fixed Code overhead Protocol support 49

Protocols (defprotocol Shape (area [shape]) (circumference [shape])) (defrecord Rectangle [vertices] Shape (area [shape]...) (circumference [shape]...)) (defrecord Circle [center r] Shape (area [shape]...) (circumference [shape]...)) 50

Protocols (defprotocol ShapeStorage (read-from [storage]) (write-to [storage shape])) (extend-protocol ShapeStorage XmlStorage (read-from [storage]...) (write-to [storage shape]...) CouchDB (read-from [storage]...) (write-to [storage shape]...)) (extend-protocol ShapeStorage String (read-from [storage]...) (write-to [storage shape]...)) 51

Protocols Performance Grouping Limited dispatch (single arg, type-based) Platform integration 52

Summary 53

Roadmap Recommendation 1 Namespaces, Functions, Persistent Data Structures 2 Multimethods 3 defrecord defprotocol 4 deftype 54

Thanks! Q&A innoq Deutschland GmbH Krischerstr. 100 40789 Monheim am Rhein Germany Phone: +49 2173 3366-0 http://www.innoq.com innoq Schweiz GmbH Gewerbestr. 11 CH-6330 Cham Switzerland Phone: +41 41 743 0116 info@innoq.com Stefan Tilkov stefan.tilkov@innoq.com @stilkov 55