The document discusses refactoring code that sends different types of requests to a server using macros. Initially, a function is used to send requests, but it results in duplicate code. A macro is then used to generate code for sending different request types in a generic way. However, using a symbol for the parameter map causes issues at compile time, since the macro evaluator does not know the runtime values. The macro is updated to accept a list of expected parameter fields to generate setting code for each one. This allows the parameter map to remain a symbol without needing its runtime value.
2. Prerequisites
• Basic macro
(defmacro mywhen [cond-exp & clauses]
`(if ~cond-exp
(do
~@clauses)))
• Java interop
(String. "a string")
(.substring "a string" 0 5)
3. Motivation
• A script to test a server with a request
/response protocol
• To send a request to the server, reuse Java
classes that represent requests in server code
20. Refactor using macro
• It works! Hooray!
• Let’s use it for more fancy stuff.
• Optional request fields?
• On server side, SendMessage type default to
1, if not specified
25. Optional field, FAILED
• macro is evaluated at compile time, not at run
time
• macro evaluator only knows about symbols
– {:Username username :Password
password} is a map (keywords to symbols)
– But param-map is a symbol
– At compile time, macro evaluator does not know
the run time value that the symbol param-map
represents
• How do we fix it?
26. Optional field, Fixing it
• How do we fix it?
• One thought:
– Tell the macro the complete list of fields, and have
it generate codes like below for every field:
(if-let [v (:Type param-map)]
(. setType v))
• And then param-map can be a symbol whose
value macro evalutor does not need to know,
its value is only needed at run time.
30. Lessons Learned
• macro is evaluated at compile time, not at run time
• macro evaluator treats code as data
– {:Username username :Password password}
is a map of keywords to symbols, not keywrods to strings
(or whatever type username/password might be)
– But param-map is a symbol
• At compile time, macro evaluator treats ref/var as
symbol, knowing nothing about their run time values