metaprogramming ruby what the hell s a dsl
play

Metaprogramming Ruby - What the hell's a DSL? murphee (Werner - PowerPoint PPT Presentation

Metaprogramming Ruby - What the hell's a DSL? murphee (Werner Schuster) Blog @ http://jroller.com/page/murphee Meta? Programs that write Programs Compiler DSLs Regexes, anyone? Always good to start with quotes by... Alan Kay The


  1. Metaprogramming Ruby - What the hell's a DSL? ● murphee (Werner Schuster) ● Blog @ http://jroller.com/page/murphee

  2. Meta?

  3. Programs that write Programs

  4. Compiler

  5. DSLs

  6. Regexes, anyone?

  7. Always good to start with quotes by...

  8. Alan Kay

  9. The general attitude seems to be that people should wear square shoes, because squares are easier to design and manufacture than foot shaped shoes. ...

  10. If the shoe industry has gone the way of the computer industry it would now be running a $200-a- day course on how to walk, run and jump in square shoes." Alan Kay

  11. DSLs ● Internal – use host language ● External – Yacc, ANTLR, ...

  12. Executable Spec

  13. Let's start with... Dylan ● http://www.networknightvision.com/ ● Dylan ● declarative protocol spec

  14. Ethernet spec in Dylan define protocol ethernet−frame ( header−frame ) summary ”ETH %= −> %=/%s ” , source−address , destination−address , compose ( summary , payload ) ; field destination−address : : <mac−address >; field source−address : : <mac−address >; field type−code : : <2byte−big−endian−unsigned−integer >; var iably−typed−field payload , type−function: select ( frame . type−code ) #x800 => <ipv4−frame >; #x806 => <arp−frame >; otherwise => <raw−frame >; end ; end ;

  15. Ethernet spec in Dylan define protocol ethernet−frame ( header−frame ) summary ”ETH %= −> %=/%s ” , source−address , destination−address , compose ( summary , payload ) ; field destination−address : : <mac−address >; field source−address : : <mac−address >; field type−code : : <2byte−big−endian−unsigned−integer >; var iably−typed−field payload , type−function: select ( frame . type−code ) #x800 => <ipv4−frame >; #x806 => <arp−frame >; otherwise => <raw−frame >; end ; end ;

  16. Ethernet spec in Dylan define protocol ethernet−frame ( header−frame ) summary ”ETH %= −> %=/%s ” , source−address , destination−address , compose ( summary , payload ) ; field destination−address : : <mac−address >; field source−address : : <mac−address >; field type−code : : <2byte−big−endian−unsigned−integer >; var iably−typed−field payload , type−function: select ( frame . type−code ) #x800 => <ipv4−frame >; #x806 => <arp−frame >; otherwise => <raw−frame >; end ; end ;

  17. Design Process

  18. Incremental does it ● Sketching ● Make it work ● ? ● Profit!

  19. Example time http://www.infoq.com/articles/properties-metaprogramming ●

  20. Properties in Ruby/1 ● C#-like Properties in Ruby ● Why? – to piss of Java zealots

  21. Properties in Ruby/2 - Sketching class Foo property name end

  22. Properties in Ruby/2 - Sketching class Foo property name end NameError: undefined local variable or method `name' for main:Object

  23. Properties in Ruby/3 - Fix class Foo property :name end

  24. Properties in Ruby/3 - Fix class Foo property :name end NameError: undefined method `property' for main:Object

  25. Properties in Ruby/3 - Fix def property(sym) ... end class Foo property :name end

  26. Properties in Ruby/3 - Fix def property(sym) define_method("#{sym}=") do |value| instance_variable_set("@#{sym}", value) end end class Foo property :name end

  27. Properties in Ruby/3 - Fix name= def property(sym) define_method("#{sym}=") do |value| instance_variable_set("@#{sym}", value) end end class Foo property :name end

  28. Properties in Ruby/3 - Fix def property(sym) define_method("#{sym}=") do |value| instance_variable_set("@#{sym}", value) end @name end class Foo property :name end

  29. Properties in Ruby/4 - Expand def property(*sym, &bl ) # Code: Homework define_method("#{sym}=") do |value| # More Homework instance_variable_set("@#{sym}", value) end end class Tower property(:width, :height) {|val| val > 200} end

  30. What we know by now ● Class definitions are executed ● Symbols are nice ● Blocks too

  31. Another one

  32. Pattern Matching

  33. Parseweasel

  34. Ruby ParseTree foo.hello(1)

  35. Ruby ParseTree foo.hello(1) -> [:vcall, :hello, :foo, [:args, [:lit, 1] ] ]

  36. Ruby ParseTree foo.hello(1) -> [:vcall, :hello, AST as: :foo, s-expr symbolic expression [:args, [:lit, 1] ] ]

  37. ParseWeasel pattern [:vcall, :name_, :recv_, :args_]

  38. ParseWeasel pattern [:vcall, :name_,:recv_, :args_] someone.something foo.bar murphee.speak

  39. ParseWeasel pattern/2 [:vcall, :hello ,:recv_, :args_]

  40. ParseWeasel pattern/2 [:vcall, :hello ,:recv_, :args_] foo.bar foo.hello huey().lewey().hello() huey().speak

  41. ParseWeasel handlers handler ([:vcall, :hello,:recv_, :args_]) {|s| puts “Found a hello #{s[:recv]}” }

  42. ParseWeasel use case: optimizer replace( [:call, :op_, :*, [:lit, 0] ] ){|s| [:lit, 0] }

  43. ParseWeasel use case: optimizer replace([:call, :op_, :*, [:lit, 0] ]){|s| [:lit, 0] } x = foo * 0

  44. Ruby DSLs ● Keep it simple ● Stick to basics ● If it limps like a hack – it probably is one

  45. Let's push it further

  46. Let's mess up the syntax

  47. Hello LISP ( defun factorial (x) ( if (zerop x) 1 ( * x (factorial (- x 1))) ) ) ( factorial 42)

  48. Macros

  49. C Preprocessor

  50. C Preprocessor

  51. LISP Macro example: Infix (* a 42)

  52. I want my infix!

  53. LISP Macro example: Infix what I write ( infix (a * 42) )

  54. LISP Macro example: Infix (defmacro infix (one op two &rest body) `(,op ,one ,two ) ) what I write (infix (a * 42) )

  55. LISP Macro example: Infix (defmacro infix (one op two &rest body) `(,op ,one ,two ) ) what I write (infix (a * 42) ) what gets executed (* a 42)

  56. LISP Macro: real use cases ● Practical Lisp – MP3 binary parser – executable spec ● Many LISP control structures

  57. Macros in the real world ● Mathematica – D[x ^ 2] – Integrate[x ^ 3] – Expand[ x ^ 42] – ● Macro-like ● “FullForm” ~ s-expr – 3x -> Times[3, x ]

  58. Let's wrap up Practical Lisp ● – http://www.gigamonkeys.com/book/ http://ola-bini.blogspot.com/2006/09/ruby-metaprogramming-techniques.html ● http://www.infoq.com/articles/properties-metaprogramming ●

Recommend


More recommend