Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Go Pure with ClojureScript
Search
Marcelo Piva
July 13, 2019
Programming
2
180
Go Pure with ClojureScript
Marcelo Piva
July 13, 2019
Tweet
Share
More Decks by Marcelo Piva
See All by Marcelo Piva
Building a sustainable architecture
mpivaa
1
120
Maintaining consistency in distributed systems with an effect machine
mpivaa
1
280
Fun with Monads
mpivaa
2
190
Other Decks in Programming
See All in Programming
サーバーサイドのビルド時間87倍高速化
plaidtech
PRO
0
670
FindyにおけるTakumi活用と脆弱性管理のこれから
rvirus0817
0
240
AIコーディングAgentとの向き合い方
eycjur
0
250
時間軸から考えるTerraformを使う理由と留意点
fufuhu
4
210
STUNMESH-go: Wireguard NAT穿隧工具的源起與介紹
tjjh89017
0
390
オープンセミナー2025@広島「君はどこで動かすか?」アンケート結果
satoshi256kbyte
0
220
AWS発のAIエディタKiroを使ってみた
iriikeita
1
110
開発チーム・開発組織の設計改善スキルの向上
masuda220
PRO
17
9.4k
tool ディレクティブを導入してみた感想
sgash708
1
160
AHC051解法紹介
eijirou
0
640
ワープロって実は計算機で
pepepper
2
1.4k
rage against annotate_predecessor
junk0612
0
140
Featured
See All Featured
Product Roadmaps are Hard
iamctodd
PRO
54
11k
Speed Design
sergeychernyshev
32
1.1k
Building an army of robots
kneath
306
46k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1.1k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
284
13k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.9k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
51
5.6k
Six Lessons from altMBA
skipperchong
28
4k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Art, The Web, and Tiny UX
lynnandtonic
302
21k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
33
2.4k
Transcript
Go Pure with ClojureScript
Marcelo Piva Software Engineer @ Nubank @mpivaa github.com/mpivaa instagram.com/m.pivaa
None
None
?
? Why
Consistency Predictability Safety
Consistency Predictability Safety
Consistency Predictability Safety
Immutability Pure functions
Pure functions Input Output No side effects Isolated from the
world Transforms input -> output
Pure functions let eat = (food) => { let foodList
= [, , , ] if(foodList.includes(food)) { return } else { return } }
Pure functions eat() // => eat() // =>
Easy to test describe("eat", () => { it("returns when ",
() => { expect(eat()).toBe() }) })
Impure functions let eat = (food) => { let foodList
= [, , , ] if(foodList.includes(food)) { console.log() } else { console.log() } } Not testable, depends on the world
Immutability Never change a value, create a new one
Immutability Functions are black boxes, changing their input is unpredictable
Immutability Image: joy of clojure
Immutability Concurrency is easy
Consistency
Class Object Instance Inheritance Polymorphism Abstract Factory Builder Factory Method
Object Pool Prototype Singleton Adapter Bridge Composite Decorator Facade Flyweight Private Class Data Proxy Chain of responsibility Command Interpreter Iterator Mediator Memento Null Object Observer State
None
None
Immutability ❌ First class functions ✅ Consistency ❌
First class functions ✅ let temperatures = [10, 20, 30]
let celsius2fahrenheit = (t) => t * 1.8 + 32 temperatures.map(celsius2fahrenheit) // => [ 50, 68, 86 ]
First class functions ✅ let temperatures = [10, 20, 30]
let celsius2fahrenheit = (t) => t * 1.8 + 32 temperatures.map(celsius2fahrenheit) // => [ 50, 68, 86 ]
First class functions ✅ let temperatures = [10, 20, 30]
let celsius2fahrenheit = (t) => t * 1.8 + 32 temperatures.map(celsius2fahrenheit) // => [ 50, 68, 86 ]
First class functions ✅ let temperatures = [10, 20, 30]
let celsius2fahrenheit = (t) => t * 1.8 + 32 temperatures.map(celsius2fahrenheit) // => [ 50, 68, 86 ]
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { acc.status = "blocked" return acc } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "blocked"}
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { acc.status = "blocked" return acc } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "blocked"}
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { acc.status = "blocked" return acc } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "blocked"}
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { acc.status = "blocked" return acc } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "blocked"}
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { acc.status = "blocked" return acc } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "blocked"}
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { acc.status = "blocked" return acc } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "blocked"}
Spread operator const Immutability ❌
Immutability ❌
const Immutability ❌
const? const foo = {bar: 1} foo = {bar: 2}
// => SyntaxError: Identifier 'foo' has already been declared foo.bar = 2 foo // => {bar: 2}
const? const foo = {bar: 1} foo = {bar: 2}
// => SyntaxError: Identifier 'foo' has already been declared foo.bar = 2 foo // => {bar: 2}
const? const foo = {bar: 1} foo = {bar: 2}
// => SyntaxError: Identifier 'foo' has already been declared foo.bar = 2 foo // => {bar: 2}
Spread operator Immutability ❌
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { return {...acc, status: "blocked"} } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "active"}
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { return {...acc, status: "blocked"} } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "active"}
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { return {...acc, status: "blocked"} } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "active"}
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { return {...acc, status: "blocked"} } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "active"}
Immutability ❌ let account = {id: "acc-1", status: "active"} let
account2blocked = (acc) => { return {...acc, status: "blocked"} } account2blocked(account) // => {id: "acc-1", status: "blocked"} account // => {id: "acc-1", status: "active"}
Immutability ❌ Performance ❌
Immutability ❓
Consistency ❌
Consistency ❌
Consistency ❌
Consistency ❌
Consistency ❌ null undefined absent
Immutability ✅ First class functions ✅ Consistency ✅
First class functions ✅ (def temperatures [10 20 30]) (defn
celsius->fahrenheit [t] (+ 32 (* t 1.8))) (map celsius->fahrenheit temperatures) ; => [50.0 68.0 86.0]
First class functions ✅ (def temperatures [10 20 30]) (defn
celsius->fahrenheit [t] (+ 32 (* t 1.8))) (map celsius->fahrenheit temperatures) ; => [50.0 68.0 86.0]
First class functions ✅ (def temperatures [10 20 30]) (defn
celsius->fahrenheit [t] (+ 32 (* t 1.8))) (map celsius->fahrenheit temperatures) ; => [50.0 68.0 86.0]
First class functions ✅ (def temperatures [10 20 30]) (defn
celsius->fahrenheit [t] (+ 32 (* t 1.8))) (map celsius->fahrenheit temperatures) ; => [50.0 68.0 86.0]
Immutability ✅ (def account {:id "acc-1" :status :active}) (defn account->blocked
[acc] (assoc acc :status :blocked) (account->blocked account) ; => {:id "acc-1" :status :blocked} account ; => {:id "acc-1" :status :active}
Immutability ✅ (def account {:id "acc-1" :status :active}) (defn account->blocked
[acc] (assoc acc :status :blocked) (account->blocked account) ; => {:id "acc-1" :status :blocked} account ; => {:id "acc-1" :status :active}
Immutability ✅ (def account {:id "acc-1" :status :active}) (defn account->blocked
[acc] (assoc acc :status :blocked) (account->blocked account) ; => {:id "acc-1" :status :blocked} account ; => {:id "acc-1" :status :active}
Immutability ✅ (def account {:id "acc-1" :status :active}) (defn account->blocked
[acc] (assoc acc :status :blocked) (account->blocked account) ; => {:id "acc-1" :status :blocked} account ; => {:id "acc-1" :status :active}
Immutability ✅ (def account {:id "acc-1" :status :active}) (defn account->blocked
[acc] (assoc acc :status :blocked) (account->blocked account) ; => {:id "acc-1" :status :blocked} account ; => {:id "acc-1" :status :active}
Structural Sharing A =
Structural Sharing A = B =
Structural Sharing
Structural Sharing A
Structural Sharing B
Consistency ✅
Consistency ✅ Only nil
None
JVM Bytecode
JVM Bytecode Node / Browser Javascript
Interop Using JS inside ClojureScript
React
is a LISP
None
LISP LISt Processing
LISP Developed in 1959
LISP Multiple dialects
JS was based on a LISP Based on Scheme, a
LISP dialect
LISP (10 20 30)
LISP No Syntax, everything is a LIST (defn celsius->fahrenheit [t]
(+ 32 (* t 1.8)))
LISP No Syntax, everything is a LIST (defn celsius->fahrenheit [t]
(+ 32 (* t 1.8)))
LISP No Syntax, everything is a LIST (defn celsius->fahrenheit [t]
(+ 32 (* t 1.8)))
LISP No Syntax, everything is a LIST (defn celsius->fahrenheit [t]
(+ 32 (* t 1.8)))
LISP Homoiconic: CODE = DATA (defn celsius->fahrenheit [t] (+ 32
(* t 1.8)))
Dynamic Code easy to manipulate
None
Macros Functions that generate code
Macros Resolved in compile time
Macros Unless macro
Macros Unless macro
Macros Unless macro
Macros Unless macro
Pipeline operator ⚠
Threading macro
Threading macro
Threading macro
Types
Types
Pattern matching ⚠
Pattern matching ⚠
None
REPL Read Eval Print Loop
None
REPL Change code on runtime
Consistency Predictability Safety
?
None
Thanks! We're hiring! @mpivaa github.com/mpivaa instagram.com/m.pivaa https://nubank.workable.com/ https://t.me/clojurebrasil https://www.braveclojure.com