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
200
Other Decks in Programming
See All in Programming
生成 AI 時代のスナップショットテストってやつを見せてあげますよ(α版)
ojun9
0
310
メッセージングを利用して時間的結合を分離しよう #phperkaigi
kajitack
3
480
おれのAgentic Coding 2026/03
tsukasagr
1
120
存在論的プログラミング: 時間と存在を記述する
koriym
5
560
LM Linkで(非力な!)ノートPCでローカルLLM
seosoft
0
260
PHPで TLSのプロトコルを実装してみる
higaki_program
0
530
Geminiをパートナーに神社DXシステムを個人開発した話(いなめぐDX 開発振り返り)
fujiba
0
120
Mastering Event Sourcing: Your Parents Holidayed in Yugoslavia
super_marek
0
120
AI時代のシステム設計:ドメインモデルで変更しやすさを守る設計戦略
masuda220
PRO
6
1.1k
Windows on Ryzen and I
seosoft
0
420
Cyrius ーLinux非依存にコンテナをネイティブ実行する専用OSー
n4mlz
0
250
GoのDB アクセスにおける 「型安全」と「柔軟性」の両立 - Bob という選択肢
tak848
0
280
Featured
See All Featured
Building AI with AI
inesmontani
PRO
1
820
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.2k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.1k
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.8k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
160
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.2k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
480
Reality Check: Gamification 10 Years Later
codingconduct
0
2.1k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
68
38k
Designing for humans not robots
tammielis
254
26k
Everyday Curiosity
cassininazir
0
180
Marketing to machines
jonoalderson
1
5.1k
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