"We just started holding 20 minutes presentations during lunch time in the ThoughtWorks Sydney office. For the first session I gave a not-that-short talk on Lisp macros using Clojure. The slides are below.
It turns out that 20 minutes is too little time to actually acquire content but I think at least we now have some people interested in how metaprogramming can be more than monkey patching."
http://fragmental.tw/2009/01/20/presentation-slides-macros-in-20-minutes/
9. Ruby - Quick Hack
names = [quot;Burkequot;, quot;Connorquot;, quot;Frankquot;,
quot;Everettquot;, quot;Albertquot;, quot;Georgequot;,
quot;Harrisquot;, quot;Davidquot;]
query = from :n => names do
where n.length => 5
orderby n
select n.upcase
end
query.each{|e| puts e }
10. Clojure
(def names '(quot;Burkequot;, quot;Connorquot;, quot;Frankquot;,
quot;Everettquot;, quot;Albertquot;,
quot;Georgequot;, quot;Harrisquot;,
quot;Davidquot;))
(def query
(from n in names
where (= (. n length) 5)
orderby n
select (. n toUpperCase)))
(doseq [n query] (println n))
11. Ruby Hack - Implementation
class Parameter def from(binding, &spec)
def method_missing(method, *args) var = binding.keys.first
method list = binding.values.last
end query = Query.new var
end query.instance_eval &spec
list.select do |a|
class Query a.send(query.condition[:method]) ==
attr_reader :condition, :criteria, :action query.condition[:value]
end.sort do |a,b|
def initialize(var) if(query.criteria)
singleton_class.send(:define_method, var) a.send(query.criteria) <=> b.send(query.criteria)
{ Parameter.new } else
end a <=> b
end
def singleton_class; class << self; self; end; end end.map do |a|
a.send(query.action)
def where(cond) end
@condition = {:method => cond.keys.first, :value => end
cond.values.last}
end
def orderby(criteria)
@criteria = criteria unless criteria.kind_of?
Parameter
end
def select(action)
@action = action
end
end
a <=> b
end
end.map do |a|
a.send(query.action)
end
end
13. Code is Data
Data is Code
“ InfoQ: [...] many modern programming languages like Ruby are claiming big
influences from Lisp Have you seen those languages or do you have any ideas
about the current state of programming languages?
McCarthy: [...] I don't know enough for example about Ruby to know in what way
it's related to Lisp. Does it use, for example, list structures as data?
InfoQ: No.
McCarthy: So if you want to compute with sums and products, you have to parse
every time?
InfoQ: Yes.
McCarthy: So, in that respect Ruby still isn't up to where Lisp was in 1960.
Adapted From: http://www.infoq.com/interviews/mccarthy-elephant-2000*
24. (defn they-are-the-same []
(println quot;They are the same!quot;))
(defn they-are-different []
(println quot;They are different!quot;))
(my-if (= 2 2)
(they-are-the-same)
(they-are-different))
25. First Try: Function
(defn my-if [condition succ fail]
(cond
condition succ
:else fail))
user>
;;;; (my-if (= 2 2) (they-are-the-
same) (they-are ...
They are the same!
They are different!
26. Second Try: Macro
(defmacro my-if [condition succ fail]
(cond
condition succ
:else fail))
user>
;;;; (my-if (= 2 2) (they-are-the-
same) (they-are ...
They are the same!
27. Why? Dump Function Arguments
(defn my-if [condition succ fail]
(println quot;Parameters are: quot; condition
succ fail))
user>
user>
;;;; (my-if (= 2 2) (they-are-the-
same) (they-are ...
They are the same!
They are different!
Parameters are: true nil nil