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
110
Maintaining consistency in distributed systems with an effect machine
mpivaa
1
270
Fun with Monads
mpivaa
2
190
Other Decks in Programming
See All in Programming
DroidKnights 2025 - 다양한 스크롤 뷰에서의 영상 재생
gaeun5744
3
320
ruby.wasmで多人数リアルタイム通信ゲームを作ろう
lnit
2
270
エンジニア向け採用ピッチ資料
inusan
0
160
第9回 情シス転職ミートアップ 株式会社IVRy(アイブリー)の紹介
ivry_presentationmaterials
1
240
FormFlow - Build Stunning Multistep Forms
yceruto
1
190
XP, Testing and ninja testing
m_seki
3
190
CursorはMCPを使った方が良いぞ
taigakono
1
180
生成AIコーディングとの向き合い方、AIと共創するという考え方 / How to deal with generative AI coding and the concept of co-creating with AI
seike460
PRO
1
330
[初登壇@jAZUG]アプリ開発者が気になるGoogleCloud/Azure+wasm/wasi
asaringo
0
130
なぜ「共通化」を考え、失敗を繰り返すのか
rinchoku
1
510
たった 1 枚の PHP ファイルで実装する MCP サーバ / MCP Server with Vanilla PHP
okashoi
1
190
プロダクト志向なエンジニアがもう一歩先の価値を目指すために意識したこと
nealle
0
110
Featured
See All Featured
A Tale of Four Properties
chriscoyier
160
23k
Site-Speed That Sticks
csswizardry
10
660
Why Our Code Smells
bkeepers
PRO
337
57k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.4k
A Modern Web Designer's Workflow
chriscoyier
694
190k
It's Worth the Effort
3n
185
28k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
Stop Working from a Prison Cell
hatefulcrawdad
270
20k
Designing for humans not robots
tammielis
253
25k
Making Projects Easy
brettharned
116
6.3k
Into the Great Unknown - MozCon
thekraken
39
1.9k
Gamification - CAS2011
davidbonilla
81
5.3k
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