SlideShare ist ein Scribd-Unternehmen logo
1 von 28
Downloaden Sie, um offline zu lesen
Writing Macros
Chapter 8 of CLOJURE for the BRAVE and TRUE
( LINK : http://www.braveclojure.com/writing-macros/ )
2016/8/11 - ClojureTW 讀書會 @ 摩茲工寮, 台北
Macros Are Essential
● Macros are an integral part of Clojure development
— they’re even used to provide fundamental operations.
● EXAMPLE: “ when ” = “ if ” + “ do ”
( macroexpand ‘( when boolean-expression
expression-1
expression-2
expression-3))
; => (if boolean-expression
; (do expression-1
; expression-2
; expression-3))
Anatomy of a Macro
Macros receive unevaluated, arbitrary data structures as arguments and
return data structures that Clojure evaluates
defmacro defn
(evaluated)
Building Lists for Evaluation
● Macro writing is all about building a list for Clojure to evaluate
defmacro final list to evaluate
unevaluated arguments
Building Lists for Evaluation
● Macro writing is all about building a list for Clojure to evaluate
(defmacro infix-2
[[operand1 op operand2]]
(list op operand1 operand2))
Building Lists for Evaluation
● You’ll need to be extra careful about the difference
between a symbol and its value
Macro
(building lists)
closed-box
(list of symbol)
Evaluation
Building Lists for Evaluation
● You’ll need to be extra careful about the difference
between a symbol and its value
(defmacro my-print-whoopsie
[expression]
(list let [result expression]
(list println result)
result))
EXCEPTION
Building Lists for Evaluation
● You’ll need to be extra careful about the difference
between a symbol and its value
(defmacro my-print-whoopsie
[expression]
(list 'let ['result expression]
(list 'println 'result)
result))
OK!
Building Lists for Evaluation
Single Quoting vs. Syntax Quoting
'+
; => +
`+
; => clojure.core/+
Syntax quoting will always include the symbol’s full namespace
→ Help you avoid name collisions
Building Lists for Evaluation
Single Quoting vs. Syntax Quoting
'(+ 1 ~(inc 1))
; => (+ 1 ~(inc 1))
`(+ 1 ~(inc 1))
; => (clojure.core/+ 1 2)
full namespace evaluated instead of being quoted!
Building Lists for Evaluation
Single Quoting vs. Syntax Quoting
The other difference between quoting and syntax quoting is that the latter
allows you to unquote forms using the tilde, ~
( q u o t e d )
‘
( q u o t e d
` ~ ( evaluated ) q u o t e d )
Using Syntax Quoting in a Macro
If you want your macro to return multiple forms for Clojure to evaluate,
make sure to wrap them in a do.
(defmacro code-critic
"Phrases are courtesy Hermes Conrad from Futurama"
[bad good]
`(do (println "Great squid of Madrid, this is bad code:"
(quote ~bad))
(println "Sweet gorilla of Manila, this is good code:"
(quote ~good))))
Refactoring a Macro and Unquote Splicing
(do
((clojure.core/println "criticism" '(1 + 1))
(clojure.core/println "criticism" '(+ 1 1))))
(do
(nil nil))
EXCEPTION
NullPointerException
nil function nil argument
Unquote splicing was invented precisely to handle this kind of situation
Refactoring a Macro and Unquote Splicing
`(+ ~(list 1 2 3))
; => (clojure.core/+ (1 2 3))
`(+ ~@(list 1 2 3))
; => (clojure.core/+ 1 2 3) Great !
(defmacro code-critic
[{:keys [good bad]}]
`(do ~@(map #(apply criticize-code %)
[["Sweet lion of Zion, this is bad code:" bad]
["Great cow of Moscow, this is good code:"
good]])))
do & map
so convenient !
Refactoring a Macro and Unquote Splicing
( q u o t e d
` ~ ( evaluated ) q u o t e d )
( q u o t e d )
‘
( q u o t e d
` ~ ( evaluated ) q u o t e d )@
Unquote
simple function
simple function
+ do, map … etc.
Things to Watch Out For
1. Variable Capture
(def message "Good job!")
(defmacro with-mischief
[& stuff-to-do]
(concat (list 'let ['message "Oh, big deal!"])
stuff-to-do))
(with-mischief
(println "Here's how I feel about that thing you did: " message))
; => Here's how I feel about that thing you did:Oh, big deal!
Things to Watch Out For
1. Variable Capture
Uncorrelated Macro
letB -> C
function
( input: A)
( output: A)
function
( input: A)
( B ->C)
( output: A)
function
( input: B)
( B ->C)
( output: C)
B
B
B
C
Things to Watch Out For
1. Variable Capture
(def message "Good job!")
(defmacro with-mischief
[& stuff-to-do]
`(let [message "Oh, big deal!" ]
~@stuff-to-do))
(with-mischief
(println "Here's how I feel about that thing you did: " message))
; Exception: Can't let qualified name: user/message
Syntax quoting is designed to prevent you from accidentally capturing
variables within macros.
Things to Watch Out For
1. Variable Capture
(defmacro without-mischief
[& stuff-to-do]
(let [macro-message (gensym 'message)]
`(let [~macro-message "Oh, big deal!" ]
~@stuff-to-do
(println "I still need to say: " ~macro-message))))
(without-mischief
(println "Here's how I feel about that thing you did: " message))
; => Here's how I feel about that thing you did: Good job!
(gensym 'message)
; => message4763
Symbol prefix !
This example avoids variable capture by using gensym to create a new, unique
symbol that then gets bound to macro-variable.
Things to Watch Out For
1. Variable Capture
Uncorrelated Macro
gensym let B -> C
function
( input: A)
( output: A)
function
( input: A)
( gensym B ->C)
( output: A)
function
( input: B)
( B123 ->C)
( output: B)
B
B
B
B
Things to Watch Out For
1. Variable Capture
`(blarg# blarg#)
(blarg__2869__auto__ blarg__2869__auto__)
`(let [name# "Larry Potter" ] name#)
; => (clojure.core/let [name__2872__auto__ "Larry Potter"]
name__2872__auto__)
Because this is such a common pattern, you can use an auto-gensym.
Auto-gensyms are more concise and convenient ways to use gensyms
Things to Watch Out For
( q u o t e d
` ~ ( evaluated ) q u o t e d )
( q u o t e d
` ~ ( evaluated ) q u o t e d )@
Unquote
+ do, map … etc.
( quoted
` ~ ( evaluated )( let [ var # … ]
autogem
Things to Watch Out For
2. Double Evaluation
(defmacro report
[to-try]
`(if ~to-try
(println (quote ~to-try) "was successful:" ~to-try)
(println (quote ~to-try) "was not successful:" ~to-try)))
1
2
3
Things to Watch Out For
2. Double Evaluation
Repeated actions in Macro
let repeat 100 times
function
( input: A)
a lot of calc
( output: A)
function
( input: A)
a lot of
repeating calc
( output: A)
B
B
B
function
( input: A)
a lot of
repeating calc
( output: A)
Waiting for
calculation process ….
Things to Watch Out For
2. Double Evaluation
(defmacro report
[to-try]
`(if ~to-try
(println (quote ~to-try) "was successful:" ~to-try)
(println (quote ~to-try) "was not successful:" ~to-try)))
1
2
3
(defmacro report
[to-try]
`(let [result# ~to-try]
(if result#
(println (quote ~to-try) "was successful:" result#)
(println (quote ~to-try) "was not successful:" result#))))
1 Double eval ? → let
→ Var capture ? → auto-gensym
Things to Watch Out For
3. Macros All the Way Down
(doseq [code ['(= 1 1) '(= 1 2)]]
(report code))
; => code was successful: (= 1 1)
; => code was successful: (= 1 2)
(defmacro doseq-macro
[macroname & args]
`(do
~@(map (fn [arg] (list macroname arg)) args)))
(doseq-macro report (= 1 1) (= 1 2))
; => (= 1 1) was successful: true
; => (= 1 2) was not successful: false
report operating at macro expansion
time, just can’t access those values.
To resolve this situation,
you might write another macro
Things to Watch Out For
3. Macros All the Way Down
● It’s easy to paint yourself into a corner, making it impossible to
accomplish anything with run-of-the-mill function calls.
● They only really compose with each other, so by using them, you might be
missing out on the other kinds of composition (functional,
object-oriented) available to you in Clojure.
Macro Macro
Macro
Macro
Macro
Macro
Macro
Macro
Macro
Macro
Macro
Macro
Summary
Don’t listen to these prudes
— at least, not at first! Go out there and have a good time.
That’s the only way you’ll learn the situations where it’s appropriate
to use macros. You’ll come out the other side knowing how to use
macros with skill and panache.

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
 
JavaScript Control Statements I
JavaScript Control Statements IJavaScript Control Statements I
JavaScript Control Statements I
 
C# 6.0 Preview
C# 6.0 PreviewC# 6.0 Preview
C# 6.0 Preview
 
The Ring programming language version 1.7 book - Part 85 of 196
The Ring programming language version 1.7 book - Part 85 of 196The Ring programming language version 1.7 book - Part 85 of 196
The Ring programming language version 1.7 book - Part 85 of 196
 
classes & objects in cpp overview
classes & objects in cpp overviewclasses & objects in cpp overview
classes & objects in cpp overview
 
The Ring programming language version 1.5.2 book - Part 78 of 181
The Ring programming language version 1.5.2 book - Part 78 of 181The Ring programming language version 1.5.2 book - Part 78 of 181
The Ring programming language version 1.5.2 book - Part 78 of 181
 
JavaScript Control Statements II
JavaScript Control Statements IIJavaScript Control Statements II
JavaScript Control Statements II
 
Iterative control structures, looping, types of loops, loop working
Iterative control structures, looping, types of loops, loop workingIterative control structures, looping, types of loops, loop working
Iterative control structures, looping, types of loops, loop working
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error Examples
 
What's New In C# 5.0 - Rumos InsideOut
What's New In C# 5.0 - Rumos InsideOutWhat's New In C# 5.0 - Rumos InsideOut
What's New In C# 5.0 - Rumos InsideOut
 
The Ring programming language version 1.10 book - Part 101 of 212
The Ring programming language version 1.10 book - Part 101 of 212The Ring programming language version 1.10 book - Part 101 of 212
The Ring programming language version 1.10 book - Part 101 of 212
 
How Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzerHow Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzer
 
Operator overloading2
Operator overloading2Operator overloading2
Operator overloading2
 
Concurrency in Programming Languages
Concurrency in Programming LanguagesConcurrency in Programming Languages
Concurrency in Programming Languages
 
Bind me if you can
Bind me if you canBind me if you can
Bind me if you can
 
Clang tidy
Clang tidyClang tidy
Clang tidy
 
Check the output of the following code then recode it to eliminate fu
 Check the output of the following code then recode it to eliminate fu Check the output of the following code then recode it to eliminate fu
Check the output of the following code then recode it to eliminate fu
 
The Ring programming language version 1.9 book - Part 94 of 210
The Ring programming language version 1.9 book - Part 94 of 210The Ring programming language version 1.9 book - Part 94 of 210
The Ring programming language version 1.9 book - Part 94 of 210
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScript
 
The Ring programming language version 1.5.1 book - Part 74 of 180
The Ring programming language version 1.5.1 book - Part 74 of 180The Ring programming language version 1.5.1 book - Part 74 of 180
The Ring programming language version 1.5.1 book - Part 74 of 180
 

Andere mochten auch

Macros in Clojure
Macros in ClojureMacros in Clojure
Macros in Clojure
sohta
 
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なものClojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
sohta
 

Andere mochten auch (19)

不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsして不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsして
 
Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013
Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013
Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013
 
Patterns
PatternsPatterns
Patterns
 
A Dive Into Clojure
A Dive Into ClojureA Dive Into Clojure
A Dive Into Clojure
 
A little exercise with clojure macro
A little exercise with clojure macroA little exercise with clojure macro
A little exercise with clojure macro
 
Clojure: Practical functional approach on JVM
Clojure: Practical functional approach on JVMClojure: Practical functional approach on JVM
Clojure: Practical functional approach on JVM
 
入門ClojureScript
入門ClojureScript入門ClojureScript
入門ClojureScript
 
Macros in Clojure
Macros in ClojureMacros in Clojure
Macros in Clojure
 
Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012
 
Clojure的魅力
Clojure的魅力Clojure的魅力
Clojure的魅力
 
Clojure概览
Clojure概览Clojure概览
Clojure概览
 
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
 
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なものClojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
 
(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)
 
Clojure: a LISP for the JVM
Clojure: a LISP for the JVMClojure: a LISP for the JVM
Clojure: a LISP for the JVM
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
DSL in Clojure
DSL in ClojureDSL in Clojure
DSL in Clojure
 
プログラミング言語Clojureのニャンパスでの活用事例
プログラミング言語Clojureのニャンパスでの活用事例プログラミング言語Clojureのニャンパスでの活用事例
プログラミング言語Clojureのニャンパスでの活用事例
 
Clojure from ground up
Clojure from ground upClojure from ground up
Clojure from ground up
 

Ähnlich wie Writing Macros

Learn a language : LISP
Learn a language : LISPLearn a language : LISP
Learn a language : LISP
Devnology
 
Introduction aux Macros
Introduction aux MacrosIntroduction aux Macros
Introduction aux Macros
univalence
 

Ähnlich wie Writing Macros (20)

Meta Object Protocols
Meta Object ProtocolsMeta Object Protocols
Meta Object Protocols
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
Clojure And Swing
Clojure And SwingClojure And Swing
Clojure And Swing
 
Functional Concepts for OOP Developers
Functional Concepts for OOP DevelopersFunctional Concepts for OOP Developers
Functional Concepts for OOP Developers
 
Learn a language : LISP
Learn a language : LISPLearn a language : LISP
Learn a language : LISP
 
Clojure basics
Clojure basicsClojure basics
Clojure basics
 
Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)
 
Go 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX GoGo 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX Go
 
關於測試,我說的其實是......
關於測試,我說的其實是......關於測試,我說的其實是......
關於測試,我說的其實是......
 
Clean Code JavaScript
Clean Code JavaScriptClean Code JavaScript
Clean Code JavaScript
 
Introduction aux Macros
Introduction aux MacrosIntroduction aux Macros
Introduction aux Macros
 
Things about Functional JavaScript
Things about Functional JavaScriptThings about Functional JavaScript
Things about Functional JavaScript
 
Introduction to julia
Introduction to juliaIntroduction to julia
Introduction to julia
 
Clojure intro
Clojure introClojure intro
Clojure intro
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
C programming language tutorial
C programming language tutorial C programming language tutorial
C programming language tutorial
 
Cpp tutorial
Cpp tutorialCpp tutorial
Cpp tutorial
 
ClojureScript: The Good Parts
ClojureScript: The Good PartsClojureScript: The Good Parts
ClojureScript: The Good Parts
 
Golang dot-testing-lite
Golang dot-testing-liteGolang dot-testing-lite
Golang dot-testing-lite
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 

Mehr von RueiCi Wang

如何推動新板Ur school網站前進
如何推動新板Ur school網站前進如何推動新板Ur school網站前進
如何推動新板Ur school網站前進
RueiCi Wang
 
UrSchool 三分鐘搞懂願景
UrSchool 三分鐘搞懂願景UrSchool 三分鐘搞懂願景
UrSchool 三分鐘搞懂願景
RueiCi Wang
 
Urschoolbookv031
Urschoolbookv031Urschoolbookv031
Urschoolbookv031
RueiCi Wang
 

Mehr von RueiCi Wang (11)

李群在機器學習中的應用(超基礎篇)
李群在機器學習中的應用(超基礎篇)李群在機器學習中的應用(超基礎篇)
李群在機器學習中的應用(超基礎篇)
 
金融市場資料的區間分析法
金融市場資料的區間分析法金融市場資料的區間分析法
金融市場資料的區間分析法
 
如何打造社會企業:重點文摘
如何打造社會企業:重點文摘如何打造社會企業:重點文摘
如何打造社會企業:重點文摘
 
[US學習資料] 如何編列組織的預算?
[US學習資料] 如何編列組織的預算?[US學習資料] 如何編列組織的預算?
[US學習資料] 如何編列組織的預算?
 
如何推動新板Ur school網站前進
如何推動新板Ur school網站前進如何推動新板Ur school網站前進
如何推動新板Ur school網站前進
 
UrSchool 三分鐘搞懂願景
UrSchool 三分鐘搞懂願景UrSchool 三分鐘搞懂願景
UrSchool 三分鐘搞懂願景
 
台師大合作提案
台師大合作提案台師大合作提案
台師大合作提案
 
Urschoolbookv031
Urschoolbookv031Urschoolbookv031
Urschoolbookv031
 
成大校園團隊招募計畫
成大校園團隊招募計畫成大校園團隊招募計畫
成大校園團隊招募計畫
 
升學諮詢概念分享會
升學諮詢概念分享會升學諮詢概念分享會
升學諮詢概念分享會
 
WikiUrSchool建置計畫
WikiUrSchool建置計畫WikiUrSchool建置計畫
WikiUrSchool建置計畫
 

Kürzlich hochgeladen

CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 

Kürzlich hochgeladen (20)

HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 

Writing Macros

  • 1. Writing Macros Chapter 8 of CLOJURE for the BRAVE and TRUE ( LINK : http://www.braveclojure.com/writing-macros/ ) 2016/8/11 - ClojureTW 讀書會 @ 摩茲工寮, 台北
  • 2. Macros Are Essential ● Macros are an integral part of Clojure development — they’re even used to provide fundamental operations. ● EXAMPLE: “ when ” = “ if ” + “ do ” ( macroexpand ‘( when boolean-expression expression-1 expression-2 expression-3)) ; => (if boolean-expression ; (do expression-1 ; expression-2 ; expression-3))
  • 3. Anatomy of a Macro Macros receive unevaluated, arbitrary data structures as arguments and return data structures that Clojure evaluates defmacro defn (evaluated)
  • 4. Building Lists for Evaluation ● Macro writing is all about building a list for Clojure to evaluate defmacro final list to evaluate unevaluated arguments
  • 5. Building Lists for Evaluation ● Macro writing is all about building a list for Clojure to evaluate (defmacro infix-2 [[operand1 op operand2]] (list op operand1 operand2))
  • 6. Building Lists for Evaluation ● You’ll need to be extra careful about the difference between a symbol and its value Macro (building lists) closed-box (list of symbol) Evaluation
  • 7. Building Lists for Evaluation ● You’ll need to be extra careful about the difference between a symbol and its value (defmacro my-print-whoopsie [expression] (list let [result expression] (list println result) result)) EXCEPTION
  • 8. Building Lists for Evaluation ● You’ll need to be extra careful about the difference between a symbol and its value (defmacro my-print-whoopsie [expression] (list 'let ['result expression] (list 'println 'result) result)) OK!
  • 9. Building Lists for Evaluation Single Quoting vs. Syntax Quoting '+ ; => + `+ ; => clojure.core/+ Syntax quoting will always include the symbol’s full namespace → Help you avoid name collisions
  • 10. Building Lists for Evaluation Single Quoting vs. Syntax Quoting '(+ 1 ~(inc 1)) ; => (+ 1 ~(inc 1)) `(+ 1 ~(inc 1)) ; => (clojure.core/+ 1 2) full namespace evaluated instead of being quoted!
  • 11. Building Lists for Evaluation Single Quoting vs. Syntax Quoting The other difference between quoting and syntax quoting is that the latter allows you to unquote forms using the tilde, ~ ( q u o t e d ) ‘ ( q u o t e d ` ~ ( evaluated ) q u o t e d )
  • 12. Using Syntax Quoting in a Macro If you want your macro to return multiple forms for Clojure to evaluate, make sure to wrap them in a do. (defmacro code-critic "Phrases are courtesy Hermes Conrad from Futurama" [bad good] `(do (println "Great squid of Madrid, this is bad code:" (quote ~bad)) (println "Sweet gorilla of Manila, this is good code:" (quote ~good))))
  • 13. Refactoring a Macro and Unquote Splicing (do ((clojure.core/println "criticism" '(1 + 1)) (clojure.core/println "criticism" '(+ 1 1)))) (do (nil nil)) EXCEPTION NullPointerException nil function nil argument Unquote splicing was invented precisely to handle this kind of situation
  • 14. Refactoring a Macro and Unquote Splicing `(+ ~(list 1 2 3)) ; => (clojure.core/+ (1 2 3)) `(+ ~@(list 1 2 3)) ; => (clojure.core/+ 1 2 3) Great ! (defmacro code-critic [{:keys [good bad]}] `(do ~@(map #(apply criticize-code %) [["Sweet lion of Zion, this is bad code:" bad] ["Great cow of Moscow, this is good code:" good]]))) do & map so convenient !
  • 15. Refactoring a Macro and Unquote Splicing ( q u o t e d ` ~ ( evaluated ) q u o t e d ) ( q u o t e d ) ‘ ( q u o t e d ` ~ ( evaluated ) q u o t e d )@ Unquote simple function simple function + do, map … etc.
  • 16. Things to Watch Out For 1. Variable Capture (def message "Good job!") (defmacro with-mischief [& stuff-to-do] (concat (list 'let ['message "Oh, big deal!"]) stuff-to-do)) (with-mischief (println "Here's how I feel about that thing you did: " message)) ; => Here's how I feel about that thing you did:Oh, big deal!
  • 17. Things to Watch Out For 1. Variable Capture Uncorrelated Macro letB -> C function ( input: A) ( output: A) function ( input: A) ( B ->C) ( output: A) function ( input: B) ( B ->C) ( output: C) B B B C
  • 18. Things to Watch Out For 1. Variable Capture (def message "Good job!") (defmacro with-mischief [& stuff-to-do] `(let [message "Oh, big deal!" ] ~@stuff-to-do)) (with-mischief (println "Here's how I feel about that thing you did: " message)) ; Exception: Can't let qualified name: user/message Syntax quoting is designed to prevent you from accidentally capturing variables within macros.
  • 19. Things to Watch Out For 1. Variable Capture (defmacro without-mischief [& stuff-to-do] (let [macro-message (gensym 'message)] `(let [~macro-message "Oh, big deal!" ] ~@stuff-to-do (println "I still need to say: " ~macro-message)))) (without-mischief (println "Here's how I feel about that thing you did: " message)) ; => Here's how I feel about that thing you did: Good job! (gensym 'message) ; => message4763 Symbol prefix ! This example avoids variable capture by using gensym to create a new, unique symbol that then gets bound to macro-variable.
  • 20. Things to Watch Out For 1. Variable Capture Uncorrelated Macro gensym let B -> C function ( input: A) ( output: A) function ( input: A) ( gensym B ->C) ( output: A) function ( input: B) ( B123 ->C) ( output: B) B B B B
  • 21. Things to Watch Out For 1. Variable Capture `(blarg# blarg#) (blarg__2869__auto__ blarg__2869__auto__) `(let [name# "Larry Potter" ] name#) ; => (clojure.core/let [name__2872__auto__ "Larry Potter"] name__2872__auto__) Because this is such a common pattern, you can use an auto-gensym. Auto-gensyms are more concise and convenient ways to use gensyms
  • 22. Things to Watch Out For ( q u o t e d ` ~ ( evaluated ) q u o t e d ) ( q u o t e d ` ~ ( evaluated ) q u o t e d )@ Unquote + do, map … etc. ( quoted ` ~ ( evaluated )( let [ var # … ] autogem
  • 23. Things to Watch Out For 2. Double Evaluation (defmacro report [to-try] `(if ~to-try (println (quote ~to-try) "was successful:" ~to-try) (println (quote ~to-try) "was not successful:" ~to-try))) 1 2 3
  • 24. Things to Watch Out For 2. Double Evaluation Repeated actions in Macro let repeat 100 times function ( input: A) a lot of calc ( output: A) function ( input: A) a lot of repeating calc ( output: A) B B B function ( input: A) a lot of repeating calc ( output: A) Waiting for calculation process ….
  • 25. Things to Watch Out For 2. Double Evaluation (defmacro report [to-try] `(if ~to-try (println (quote ~to-try) "was successful:" ~to-try) (println (quote ~to-try) "was not successful:" ~to-try))) 1 2 3 (defmacro report [to-try] `(let [result# ~to-try] (if result# (println (quote ~to-try) "was successful:" result#) (println (quote ~to-try) "was not successful:" result#)))) 1 Double eval ? → let → Var capture ? → auto-gensym
  • 26. Things to Watch Out For 3. Macros All the Way Down (doseq [code ['(= 1 1) '(= 1 2)]] (report code)) ; => code was successful: (= 1 1) ; => code was successful: (= 1 2) (defmacro doseq-macro [macroname & args] `(do ~@(map (fn [arg] (list macroname arg)) args))) (doseq-macro report (= 1 1) (= 1 2)) ; => (= 1 1) was successful: true ; => (= 1 2) was not successful: false report operating at macro expansion time, just can’t access those values. To resolve this situation, you might write another macro
  • 27. Things to Watch Out For 3. Macros All the Way Down ● It’s easy to paint yourself into a corner, making it impossible to accomplish anything with run-of-the-mill function calls. ● They only really compose with each other, so by using them, you might be missing out on the other kinds of composition (functional, object-oriented) available to you in Clojure. Macro Macro Macro Macro Macro Macro Macro Macro Macro Macro Macro Macro
  • 28. Summary Don’t listen to these prudes — at least, not at first! Go out there and have a good time. That’s the only way you’ll learn the situations where it’s appropriate to use macros. You’ll come out the other side knowing how to use macros with skill and panache.