196
Life of an immutant 3 years with Clojure

3 years with Clojure

Embed Size (px)

DESCRIPTION

An experience report from 3 years of using Clojure

Citation preview

Page 1: 3 years with Clojure

Life of an immutant3 years with Clojure

Page 2: 3 years with Clojure

About me

• @michaelklishin

• github.com/michaelklishin

Page 3: 3 years with Clojure

Setting expectations

Page 4: 3 years with Clojure

Setting expectations

• This is an experience report

Page 5: 3 years with Clojure

Setting expectations

• This is an experience report

• Not a language primer

Page 6: 3 years with Clojure

Setting expectations

• This is an experience report

• Not a language primer

• Assumes no familiarity except basic facts

Page 7: 3 years with Clojure

Setting expectations

• This is an experience report

• Not a language primer

• Assumes no familiarity except basic facts

• ~200 slides. This is gonna be fast.

Page 8: 3 years with Clojure

Background

Page 9: 3 years with Clojure

Background

• Data processing

Page 10: 3 years with Clojure

Background

• Data processing

• Scheduling systems

Page 11: 3 years with Clojure

Background

• Data processing

• Scheduling systems

• Specialized Web crawlers

Page 12: 3 years with Clojure

Background

• Data processing

• Scheduling systems

• Specialized Web crawlers

• Billing, accounting

Page 13: 3 years with Clojure

Background

• Data processing

• Scheduling systems

• Specialized Web crawlers

• Billing, accounting

• Infrastructure automation

Page 14: 3 years with Clojure

Wanted

Page 15: 3 years with Clojure

Wanted

• An environment that does not suck

Page 16: 3 years with Clojure

Wanted

• An environment that does not suck is operationally sane

Page 17: 3 years with Clojure

Wanted

• An environment that does not suck is operationally sane

• A runtime that has decent tooling (profilers, concurrency-related metrics, GC metrics)

Page 18: 3 years with Clojure

Wanted

• An environment that does not suck is operationally sane

• A runtime that has decent tooling (profilers, concurrency-related metrics, GC metrics)

• A runtime that yields good baseline performance

Page 19: 3 years with Clojure

Wanted

• An environment that does not suck is operationally sane

• A runtime that has decent tooling (profilers, concurrency-related metrics, GC metrics)

• A runtime that yields good baseline performance

• Painless upgrade paths

Page 20: 3 years with Clojure

Wanted

• Community

Page 21: 3 years with Clojure

Wanted

• Community

• Benefit from existing libraries and tools

Page 22: 3 years with Clojure

Wanted

• Community

• Benefit from existing libraries and tools

• Concurrency and parallelism

Page 23: 3 years with Clojure

Wanted

• Community

• Benefit from existing libraries and tools

• Concurrency and parallelism

• A productive, concise language

Page 24: 3 years with Clojure

Wanted

JVM

Page 25: 3 years with Clojure

JVM

Page 26: 3 years with Clojure

JVM

• One of the most mature runtimes you can find

Page 27: 3 years with Clojure

JVM

• One of the most mature runtimes you can find

• Excellent tooling

Page 28: 3 years with Clojure

JVM

• One of the most mature runtimes you can find

• Excellent tooling (Visual VM, YourKit, jstack, jhat, VM/+XX flags, BTrace, …)

Page 29: 3 years with Clojure

JVM

• One of the most mature runtimes you can find

• Excellent tooling

• Excellent baseline performance

Page 30: 3 years with Clojure

JVM

• One of the most mature runtimes you can find

• Excellent tooling

• Excellent baseline performance

• Multilingual: Clojure, Java, JRuby, Scala, JS implementations

Page 31: 3 years with Clojure
Page 32: 3 years with Clojure

Clojure

Page 33: 3 years with Clojure

Clojure

• Very high level, concise, expressive

Page 34: 3 years with Clojure

Clojure

• Very high level, concise, expressive

• Excellent concurrency/parallelism story

Page 35: 3 years with Clojure

Clojure

• Very high level, concise, expressive

• Excellent concurrency/parallelism story

• Very good baseline performance

Page 36: 3 years with Clojure

Clojure

• Very high level, concise, expressive

• Excellent concurrency/parallelism story

• Very good baseline performance

• Consistent, well designed

Page 37: 3 years with Clojure

Clojure

• Very high level, concise, expressive

• Excellent concurrency/parallelism story

• Very good baseline performance

• Consistent, well designed

• Decent tooling

Page 38: 3 years with Clojure

Clojure

• Very high level, concise, expressive

• Excellent concurrency/parallelism story

• Very good baseline performance

• Consistent, well designed

• Decent tooling

• Fun to work with (motivation)

Page 39: 3 years with Clojure

Clojure

• No bored academics, built by a practicioner

Page 40: 3 years with Clojure

Clojure: concurrency/parallelism story

Page 41: 3 years with Clojure

Clojure: concurrency/parallelism story

• Immutable data structures by default

Page 42: 3 years with Clojure

Clojure: concurrency/parallelism story

• Immutable data structures by default

• Identity/values separation

Page 43: 3 years with Clojure

Clojure: concurrency/parallelism story

• Immutable data structures by default

• Identity/values separation

• Concurrency-aware reference types

Page 44: 3 years with Clojure

Clojure: concurrency/parallelism story

• Immutable data structures by default

• Identity/values separation

• Concurrency-aware reference types

• java.util.concurrent

Page 45: 3 years with Clojure

Clojure: concurrency/parallelism story

When I find myself in times of trouble Prof. Doug Lea comes to me Coding lines of wisdom j.u.c.

Page 46: 3 years with Clojure

Clojure: concurrency/parallelism story

• Immutable data structures by default

• Identity/values separation

• Concurrency-aware reference types

• java.util.concurrent

• Reactor, Akka, Disruptor, RxJava…

Page 47: 3 years with Clojure

Clojure: concurrency/parallelism story

• Async I/O: NIO, Netty, Vert.x…

Page 48: 3 years with Clojure

Clojure: concurrency/parallelism story

• You have choice

Page 49: 3 years with Clojure

Clojure: concurrency/parallelism story

• You have choice

• Runtime parallelism (on JVM, CLR)

Page 50: 3 years with Clojure

Clojure: concurrency/parallelism story

• You have choice

• Runtime parallelism (on JVM, CLR)

• Hundreds, thousands of threads at the same time

Page 51: 3 years with Clojure
Page 52: 3 years with Clojure

Clojure: baseline performance

Page 53: 3 years with Clojure

Clojure: baseline performance

• What matters the most is what bytecode the compiler produces

Page 54: 3 years with Clojure

contextneeded.com

Page 55: 3 years with Clojure

Clojure: baseline performance

• What matters the most is what bytecode the compiler produces

• Java interop bytecode is typically the same as produced by javac

Page 56: 3 years with Clojure

Clojure: baseline performance

• What matters the most is what bytecode the compiler produces

• Java interop bytecode is typically the same as produced by javac

• Watch out for reflective calls, primitive boxing

Page 57: 3 years with Clojure

Clojure: baseline performance

• Optional type hints

Page 58: 3 years with Clojure

Clojure: baseline performance

• Optional type hints

• Type inference in simple cases

Page 59: 3 years with Clojure

Clojure: baseline performance

(let [d (java.util.Date.)] d)

Page 60: 3 years with Clojure

Clojure: baseline performance

(let [d (java.util.Date.)] d)

Page 61: 3 years with Clojure

Clojure: baseline performance

• Optional type hints

• Type inference in simple cases

Page 62: 3 years with Clojure

Clojure: baseline performance

• Optional type hints

• Type inference in simple cases

• If JVM can optimize your bytecode, things run screaming fast

Page 63: 3 years with Clojure

Clojure: baseline performance

• Optional type hints

• Type inference in simple cases

• If JVM can optimize your bytecode, things run screaming fast

• From 2% (Java lib wrappers) to 200% (naïve numerics heavy code, tight loops) penalty compared to Java

Page 64: 3 years with Clojure

Clojure: baseline performance

• Immutable data structures have O(log32 n) access complexity

Page 65: 3 years with Clojure

Clojure: baseline performance

• Immutable data structures have O(log32 n) access complexity

• Immutable data structures have associated GC tax

Page 66: 3 years with Clojure

Clojure: baseline performance

• Immutable data structures have O(log32 n) access complexity

• Immutable data structures have associated GC tax

• Focus on exploiting parallelism over squeezing µs from a single thread

Page 67: 3 years with Clojure

Clojure: baseline performance

• Poor startup time, excellent execution performance

Page 68: 3 years with Clojure

Clojure: baseline performance

• Poor startup time, excellent execution performance

• Anecdotal evidence: 10 — 50 times throughput improvements compared to Ruby in real apps

Page 69: 3 years with Clojure
Page 70: 3 years with Clojure

Clojure: stability

Page 71: 3 years with Clojure

Clojure: stability

• Have been using 1.3 since alpha1

Page 72: 3 years with Clojure

Clojure: stability

• Have been using 1.3 since alpha1

• Hit by 4 Clojure bugs in ~3 years

Page 73: 3 years with Clojure

Clojure: stability

• Have been using 1.3 since alpha1

• Hit by 4 Clojure bugs in ~3 years

• 1 bug is an edge case that is not worth fixing (I did something really stupid)

Page 74: 3 years with Clojure

Clojure: stability

• Have been using 1.3 since alpha1

• Hit by 4 Clojure bugs in ~3 years

• 1 bug is an edge case that is not worth fixing (I did something really stupid)

• Alphas more solid than GA releases of almost all other languages I’ve worked with

Page 75: 3 years with Clojure

Clojure: stability

• Hit by 4 Clojure bugs in ~3 years

• 1 bug is an edge case that is not worth fixing (I did something really stupid)

• Alphas more solid than GA releases of almost all other languages I’ve worked with

• Others (e.g. ThoughtWorks) report the same experience

Page 76: 3 years with Clojure

Clojure: stability

• Upgraded 28 apps & libraries from 1.3 to 1.4. Just 1 change due to a tricky 3rd party library. The rest was a drop-in replacement.

Page 77: 3 years with Clojure

Clojure: stability

• Upgraded 28 apps & libraries from 1.3 to 1.4. Just 1 change due to a tricky 3rd party library. The rest was a drop-in replacement.

• When upgrading is this easy, people do it happily

Page 78: 3 years with Clojure

Clojure: stability

• Upgraded 28 apps & libraries from 1.3 to 1.4. Just 1 change due to a tricky 3rd party library. The rest was a drop-in replacement.

• When upgrading is this easy, people do it happily

• No library binary compatibility hell some other JVM languages suffer from

Page 79: 3 years with Clojure

Clojure: stability

• Many active developers are conservative with versioning & calling things “done”

Page 80: 3 years with Clojure

Clojure: stability

• Many active developers are conservative with versioning & calling things “done”

• Fits JVM ecosystem maturity really well

Page 81: 3 years with Clojure

Clojure: stability

• The real reason: Clojure is small and was designed to be simple

Page 82: 3 years with Clojure

Clojure: stability

• No monkey patching (there are features that give you all the good parts of teh)

Page 83: 3 years with Clojure

Clojure: consistency

Page 84: 3 years with Clojure

Clojure: consistency

• Collections/sequences library is very unified

Page 85: 3 years with Clojure

Clojure: consistency

• Collections/sequences library is very unified

• Easy to implement your own data types that work just like core Clojure types

Page 86: 3 years with Clojure

Clojure: consistency

• Collections/sequences library is very unified

• Easy to implement your own data types that work just like core Clojure types

• Almost no “bad baggage” in the core

Page 87: 3 years with Clojure

Clojure: consistency

• Collections/sequences library is very unified

• Easy to implement your own data types that work just like core Clojure types

• Almost no “bad baggage” in the core

• The language was actually designed

Page 88: 3 years with Clojure

Clojure: deployment

Page 89: 3 years with Clojure

Clojure: deployment

• Pretty standard JVM deployment options

Page 90: 3 years with Clojure

Clojure: deployment

• Pretty standard JVM deployment options

• Compile everything AOT into a single jar (“überjar”), including dependencies, assets, etc

Page 91: 3 years with Clojure

Clojure: deployment

• Pretty standard JVM deployment options

• Compile everything AOT into a single jar (“überjar”), including dependencies, assets, etc

• A tiny shell script + start-stop-daemon

Page 92: 3 years with Clojure

Clojure: deployment

• Pretty standard JVM deployment options

• Compile everything AOT into a single jar (“überjar”), including dependencies, assets, etc

• A tiny shell script + start-stop-daemon

• Chef or Capistrano

Page 93: 3 years with Clojure

Clojure: deployment

• CloudFoundry

Page 94: 3 years with Clojure

Clojure: deployment

• CloudFoundry

• Heroku

Page 95: 3 years with Clojure

Clojure: deployment

• CloudFoundry

• Heroku

• Immutant/JBoss AS

Page 96: 3 years with Clojure

Clojure: deployment

• CloudFoundry

• Heroku

• Immutant/JBoss AS

• OpenShift

Page 97: 3 years with Clojure

Clojure: operations

Page 98: 3 years with Clojure

Clojure: operations

• VisualVM, jstack, jheap, …

Page 99: 3 years with Clojure

Clojure: operations

• VisualVM, jstack, jheap, …

• nREPL

Page 100: 3 years with Clojure

Clojure: operations

• VisualVM, jstack, jheap, …

• nREPL

• Remote REPL over HTTP(S)

Page 101: 3 years with Clojure

Clojure: operations

• VisualVM, jstack, jheap, …

• nREPL

• Remote REPL over HTTP(S)

• Not quite Erlang but still impressive

Page 102: 3 years with Clojure

Clojure: operations

• VisualGC gives real insight into what is going on with object allocation, tenuring, death rate

Page 103: 3 years with Clojure

Clojure: operations

• VisualGC gives real insight into what is going on with object allocation, tenuring, death rate

• JVM DTrace support (Solaris, SmartOS, FreeBSD, OS X)

Page 104: 3 years with Clojure

Clojure: operations

• VisualGC gives real insight into what is going on with object allocation, tenuring, death rate

• JVM DTrace support (Solaris, SmartOS, FreeBSD, OS X)

• BTrace

Page 105: 3 years with Clojure

Clojure: community

Page 106: 3 years with Clojure

Clojure: community

• Full of intelligent engineers who don’t give two shits about Hacker News

Page 107: 3 years with Clojure

Clojure: community

• Full of intelligent engineers who don’t give two shits about Hacker News

• Over 10 conferences to date

Page 108: 3 years with Clojure

Clojure: community

• Full of intelligent engineers who don’t give two shits about Hacker News

• Over 10 conferences to date

• ~10K people on the mailing list

Page 109: 3 years with Clojure

Clojure: community

• Full of intelligent engineers who don’t give two shits about Hacker News

• Over 10 conferences to date

• ~10K people on the mailing list

• Users from small and not-so-small startups to Fortune 50 corporations in finance, biotech, retail

Page 110: 3 years with Clojure

Clojure: fun to work with

Page 111: 3 years with Clojure

Clojure: fun to work with

• Profoundly changes the way you think

Page 112: 3 years with Clojure

Clojure: changes the way you think

Page 113: 3 years with Clojure

Clojure: changes the way you think

• About managing your program state

Page 114: 3 years with Clojure

Clojure: changes the way you think

• About managing your program state

• About the value of experimenting (REPL driven development)

Page 115: 3 years with Clojure

Clojure: changes the way you think

• About managing your program state

• About the value of experimenting (REPL driven development)

• About metaprogramming

Page 116: 3 years with Clojure

Clojure: changes the way you think

• About managing your program state

• About the value of experimenting (REPL driven development)

• About metaprogramming

• About isolating side effects

Page 117: 3 years with Clojure

Clojure: changes the way you think

Page 118: 3 years with Clojure

Clojure: changes the way you think

• Program = pure core + parts that communicate with the outside world (network, disk I/O)

Page 119: 3 years with Clojure

Clojure: changes the way you think

• Program = pure core + parts that communicate with the outside world (network, disk I/O)

• Pure parts are ridiculously easy to reason about, test, experiment with and reuse

Page 120: 3 years with Clojure

Clojure: changes the way you think

• Program = pure core + parts that communicate with the outside world (network, disk I/O)

• Pure parts are ridiculously easy to reason about, test, experiment with and reuse

• Typical Rails app: 95% of methods have side effects

Page 121: 3 years with Clojure

Clojure: changes the way you think

• Typical Clojure app: 40% of functions have side effects

Page 122: 3 years with Clojure

Clojure: changes the way you think

• Typical Clojure app: 40% of functions have side effects

• Anecdotal evidence: 3-4 times less time spent on tests

Page 123: 3 years with Clojure

Clojure: changes the way you think

• Typical Clojure app: 40% of functions have side effects

• Anecdotal evidence: 3-4 times less time spent on tests

• Moral of the story: make more of your code not have side effects

Page 124: 3 years with Clojure

Clojure: fun to work with

• Profoundly changes the way you think

Page 125: 3 years with Clojure

Clojure: fun to work with

• Profoundly changes the way you think

• Motivates you to learn

Page 126: 3 years with Clojure

Clojure: fun to work with

• Profoundly changes the way you think

• Motivates you to learn

• Easy things are easy, hard things are possible

Page 127: 3 years with Clojure

Clojure: fun to work with

• Profoundly changes the way you think

• Motivates you to learn

• Easy things are easy, hard things are possible

• Wheels are already invented in clojure.core or JDK

Page 128: 3 years with Clojure

Clojure: fun to work with

• Stable: fewer distractions, get in the flow

Page 129: 3 years with Clojure

Clojure: fun to work with

• Stable: fewer distractions, get in the flow

• REPL driven development keeps you in the flow for longer periods

Page 130: 3 years with Clojure

Clojure: fun to work with

• Stable: fewer distractions, get in the flow

• REPL driven development keeps you in the flow for longer periods

• Polymorphism done right <3

Page 131: 3 years with Clojure

Clojure: fun to work with

“Clojure demands that you raise your game and rewards you greatly for it…”

Page 132: 3 years with Clojure

Clojure: fun to work with

• The community is full of smart and down to earth people.

Page 133: 3 years with Clojure
Page 134: 3 years with Clojure

Clojure: use cases

Page 135: 3 years with Clojure

Clojure: use cases

• Data processing

Page 136: 3 years with Clojure

Clojure: use cases

• Data processing

• Stream processing

Page 137: 3 years with Clojure

Clojure: use cases

• Data processing

• Stream processing

• Micro-services

Page 138: 3 years with Clojure

Clojure: use cases

• Data processing

• Stream processing

• Micro-services

• Machine learning

Page 139: 3 years with Clojure

Clojure: use cases

• Data processing

• Stream processing

• Micro-services

• Machine learning

• Web development

Page 140: 3 years with Clojure
Page 141: 3 years with Clojure

Clojure: misc

Page 142: 3 years with Clojure

Clojure: misc

• Leiningen (leiningen.org) is excellent

Page 143: 3 years with Clojure

Clojure: misc

• Leiningen (leiningen.org) is excellent

• Deps management, build tool, custom tasks are just Clojure functions

Page 144: 3 years with Clojure

Clojure: misc

• Leiningen (leiningen.org) is excellent

• Deps management, build tool, custom tasks are just Clojure functions

• Packages your code + all deps into a single jar for deployment

Page 145: 3 years with Clojure

Clojure: misc

• Leiningen (leiningen.org) is excellent

• Deps management, build tool, custom tasks are just Clojure functions

• Packages your code + all deps into a single jar for deployment

• Makes it trivial to develop against multiple Clojure versions

Page 146: 3 years with Clojure

Clojure: misc

• clojars.org

Page 147: 3 years with Clojure

Clojure: misc

• clojars.org

• Deploy via SSH (SCP) or HTTPS

Page 148: 3 years with Clojure

Clojure: misc

• clojars.org

• Deploy via SSH (SCP) or HTTPS

• Very easy to deploy snapshot releases

Page 149: 3 years with Clojure

Clojure: misc

• clojars.org

• Deploy via SSH (SCP) or HTTPS

• Very easy to deploy snapshot releases

• Clojars and Leiningen are maintained by the same core team

Page 150: 3 years with Clojure

Clojure: misc

• travis-ci.org support

Page 151: 3 years with Clojure

Clojure: misc

• travis-ci.org support

• Test against multiple JDKs

Page 152: 3 years with Clojure

Clojure: ecosystem

• Feels a bit like Ruby circa 2009

Page 153: 3 years with Clojure

Clojure: ecosystem

• Feels a bit like Ruby circa 2009

• But with the entire JVM ecosystem at your reach

Page 154: 3 years with Clojure

Clojure: ecosystem

• Feels a bit like Ruby circa 2009

• But with the entire JVM ecosystem at your reach

• And Leiningen + clojars.org

Page 155: 3 years with Clojure

Clojure: ecosystem

• Feels a bit like Ruby circa 2009

• But with the entire JVM ecosystem at your reach

• And Leiningen + clojars.org

• Community ~ doubles every year in size

Page 156: 3 years with Clojure

Clojure: ecosystem

• Feels a bit like Ruby circa 2009

• But with the entire JVM ecosystem at your reach

• And Leiningen + clojars.org

• Community ~ doubles every year in size

• Google for “The State of Clojure” survey

Page 157: 3 years with Clojure

Clojure: ecosystem

• ~35% of people come from Java, ~35% from Ruby or Python

Page 158: 3 years with Clojure

Clojure: ecosystem

• ~35% of people come from Java, ~35% from Ruby or Python

• Libraries, not frameworks

Page 159: 3 years with Clojure

Clojure: ecosystem

• ~35% of people come from Java, ~35% from Ruby or Python

• Libraries, not frameworks

• Decent libraries just for almost every problem

Page 160: 3 years with Clojure

Clojure: ecosystem

• ~35% of people come from Java, ~35% from Ruby or Python

• Libraries, not frameworks

• Decent libraries just for almost every problem

• 15 books, 2 outdated (cover 1.2)

Page 161: 3 years with Clojure

Clojure: ecosystem

• ~35% of people come from Java, ~35% from Ruby or Python

• Libraries, not frameworks

• Decent libraries just for almost every problem

• 15 books, 2 outdated (cover 1.2)

• clojure-doc.org, tryclj.com, …

Page 162: 3 years with Clojure

Clojure: ecosystem

Page 163: 3 years with Clojure
Page 164: 3 years with Clojure

Clojure: what sucks

Page 165: 3 years with Clojure

Clojure: what sucks

• clojure.org

Page 166: 3 years with Clojure

Clojure: what sucks

• clojure.org

• Documentation (guides, the ref is mostly OK, books are great)

Page 167: 3 years with Clojure

Clojure: what sucks

• clojure.org

• Documentation (guides, the ref is mostly OK, books are great)

• Compiler messages can be cryptic

Page 168: 3 years with Clojure

Clojure: what sucks

• clojure.org

• Documentation (guides, the ref is mostly OK, books are great)

• Compiler messages can be cryptic

• JVM startup time + code compilation on each run (without REPL or tools such as Drip)

Page 169: 3 years with Clojure

Clojure: what sucks

• Paper contributor agreement

Page 170: 3 years with Clojure
Page 171: 3 years with Clojure

ClojureWerkz

Page 172: 3 years with Clojure

ClojureWerkz

“A growing collection of open source Clojure libraries…”

Page 173: 3 years with Clojure

ClojureWerkz

“It just werkz…”

Page 174: 3 years with Clojure

ClojureWerkz

• Modern targets (Clojure 1.5+, JDK 6)

Page 175: 3 years with Clojure

ClojureWerkz

• Modern targets (Clojure 1.5+, JDK 6)

• Feature rich

Page 176: 3 years with Clojure

ClojureWerkz

• Modern targets (Clojure 1.5+, JDK 6)

• Feature rich

• Well documented

Page 177: 3 years with Clojure

ClojureWerkz

• Modern targets (Clojure 1.5+, JDK 6)

• Feature rich

• Well documented

• Friendly license (EPL, the same as Clojure)

Page 178: 3 years with Clojure

ClojureWerkz

• Modern targets (Clojure 1.5+, JDK 6)

• Feature rich

• Well documented

• Friendly license (EPL, the same as Clojure)

• Tested against multiple Clojure versions, 3 JDKs on travis-ci.org

Page 179: 3 years with Clojure

ClojureWerkz

clojurewerkz.org

Page 180: 3 years with Clojure

ClojureWerkz

• Projects reuse a lot of Java libraries

Page 181: 3 years with Clojure

ClojureWerkz

• Projects reuse a lot of Java libraries

• Which are often officially supported (e.g. RabbitMQ, ElasticSearch, MongoDB, Riak, Reactor)

Page 182: 3 years with Clojure

“ClojureWerkz stuff is really improving my Clojure experience, which is rapidly becoming my language of choice…”

Page 183: 3 years with Clojure
Page 184: 3 years with Clojure

Clojure: the takeaway

Page 185: 3 years with Clojure

Clojure: the takeaway

• A lot of merit of its own

Page 186: 3 years with Clojure

Clojure: the takeaway

• A lot of merit of its own

• Great stability

Page 187: 3 years with Clojure

Clojure: the takeaway

• A lot of merit of its own

• Great stability

• Hosted (symbiotic) language is a great thing

Page 188: 3 years with Clojure

Clojure: the takeaway

• A lot of merit of its own

• Great stability

• Hosted (symbiotic) language is a great thing

• Don’t fear the JVM

Page 189: 3 years with Clojure

Clojure: the takeaway

• A lot of merit of its own

• Great stability

• Hosted (symbiotic) language is a great thing

• Don’t fear the JVM

• Immutability is essential for sane concurrent programming

Page 190: 3 years with Clojure

Clojure: the takeaway

• Clojure greatly rewards those who choose to use it

Page 191: 3 years with Clojure
Page 192: 3 years with Clojure

The real reason?

Page 193: 3 years with Clojure
Page 194: 3 years with Clojure

The real reason?

???

Page 195: 3 years with Clojure

clojure.core/lazy-cat

Page 196: 3 years with Clojure

Thank you

• @michaelklishin

• github.com/michaelklishin

• clojurewerkz.org

[email protected]