presenation by Glenn Vanderburg
What is meta programming? It’s Programming your programming language
Rubyist have been discovering metaprogramming. Ruby style and idioms are still changing and adapting
Ruby good for metaprogramming b/c
- Dynamic and reflexive – everything is open – blocks allow writing new control structures – most declarations are executable statements – only slightly less malleable than lisp (no macros) – unobtrusive
Examples…
attr_reader, attr_writer, and attr_accessor.
if written in ruby attr_reader would be written like (actually written in C ) precode class Module def attr_reader(*syms) syms.each do |sym| class_eval %{ def #{sym} @#{sym} end } end end /code/pre
Speaker goes through several implementations over time of different ways different people did metaprogramming with ruby.
How to think about metaprogramming
- Definiting new constructs for your programming Language
- so what do the constructs to? whatever you domain needs it to do.
Another way to think about metaprogramming is a new set of conceptual tools for eliminating duplication (and other smells) from your code.
And another way to think about it is how rails does it – almost as if you can talk you code – PersonTable has_a :name
Most DSLs also deal with other things ou don’t usually find in general-purpose languages
- Context dependence
- commands and sentences
- Units
- Large vocabularies
- Heirachy
Contexts – context for a new set of statements – a new scope (not in 1.8, but in 1.9) precode Struct.new(“Interval”, :start, :end) do def length @start – @end end end /code/pre
Backend code looks like if you wanted to add it to 1.8 precode class Struct initialize(*args, block) struct_class = #define struct using args struct_class_class_eval(block) if block_given? end end /code/pre
Another example of context from Systir system testing tool
precode add_user { name “Charles” password “secret” priviliges normal } /code/pre
Commands and Sentences
Multipart complex statements
ex. field(autoinc, :reg_id, pk) Overall, it’s just a methodcall – the first parameter – the type – is a method call precode def autoinc return FieldType::AutoInc.instance end /code/pre
Units
Domain specific – general purpose language deals with scalars – programs must maintain their knowledge ex 3.days.from_now Watch out for operator overloading
precode class Numeric def days self * 60 end end /code/pre
Large Vocabularies
override method_missing
Usage: Roman.XXII Roman.CCIX precode class Roman def self.missing_method(method_id) str = method_id.id2name roman_to_int(str) end def roman_to_int(string) … end end /code/pre
Resources:
http://www.vanderburg.org/Speaking/Stuff/oscon05.pdf http://hypermetrics.com/rubyhacker/coralbook/