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
190
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
290
Fun with Monads
mpivaa
2
190
Other Decks in Programming
See All in Programming
AI巻き込み型コードレビューのススメ
nealle
0
130
Oxlint JS plugins
kazupon
1
770
AI Agent の開発と運用を支える Durable Execution #AgentsInProd
izumin5210
7
2.3k
例外処理とどう使い分ける?Result型を使ったエラー設計 #burikaigi
kajitack
16
6k
OCaml 5でモダンな並列プログラミングを Enjoyしよう!
haochenx
0
140
Spinner 軸ズレ現象を調べたらレンダリング深淵に飲まれた #レバテックMeetup
bengo4com
1
230
疑似コードによるプロンプト記述、どのくらい正確に実行される?
kokuyouwind
0
380
開発者から情シスまで - 多様なユーザー層に届けるAPI提供戦略 / Postman API Night Okinawa 2026 Winter
tasshi
0
200
コントリビューターによるDenoのすゝめ / Deno Recommendations by a Contributor
petamoriken
0
200
Fragmented Architectures
denyspoltorak
0
150
プロダクトオーナーから見たSOC2 _SOC2ゆるミートアップ#2
kekekenta
0
200
なぜSQLはAIぽく見えるのか/why does SQL look AI like
florets1
0
450
Featured
See All Featured
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
730
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
320
Exploring anti-patterns in Rails
aemeredith
2
250
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
55
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.4k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
62
49k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
117
110k
We Are The Robots
honzajavorek
0
160
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
0
140
Optimising Largest Contentful Paint
csswizardry
37
3.6k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
380
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