• Like
Metaprogramming in Ruby
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Metaprogramming in Ruby

  • 2,083 views
Published

Domain specific languages

Domain specific languages

Published in Technology , Education
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
2,083
On SlideShare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
151
Comments
0
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Introduction DSL implementation Summary Metaprogramming in Ruby Domain specific languages Peter Vanbroekhoven peter@xaop.com BRUG meeting October 3 2007 Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 2. Introduction DSL implementation Summary Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 3. Introduction DSL implementation Summary Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 4. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 5. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary What Is Metaprogramming? Programming your programming Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 6. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary What Is Metaprogramming? Metaprogramming is a good thing Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 7. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary The Deal With Metaprogramming class ActiveRecord : : Base def r e a d _ a t t r i b u t e ( attr_name ) @ a t t r i b u t e s [ attr_name ] end end class MicrosoftCEO < ActiveRecord : : Base end b i l l = MicrosoftCEO . new my_pocket << b i l l . r e a d _ a t t r i b u t e ( quot; money quot; ) Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 8. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary The Deal With Metaprogramming class MicrosoftCEO < ActiveRecord : : Base def money @ a t t r i b u t e s [ quot; money quot; ] end end b i l l = MicrosoftCEO . new my_pocket << b i l l . money Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 9. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary The Deal With Metaprogramming class MicrosoftCEO < ActiveRecord : : Base def money @ a t t r i b u t e s [ quot; money quot; ] end def house @ a t t r i b u t e s [ quot; house quot; ] end def c a r @attributes [ quot; car quot; ] end end b i l l = MicrosoftCEO . new my_pocket << b i l l . money << b i l l . house << b i l l . c a r Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 10. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary The Deal With Metaprogramming class MicrosoftCEO < ActiveRecord : : Base [ quot; money quot; , quot; house quot; , quot; c a r quot; ] . each do | f | define_method ( f ) { @ a t t r i b u t e s [ f ] } end end b i l l = MicrosoftCEO . new my_pocket << b i l l . money << b i l l . house << b i l l . c a r Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 11. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Examples of metaprogramming Java compiler Ruby interpreter Firefox browser Ruby on Rails Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 12. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Examples of metaprogramming Java compiler Ruby interpreter Firefox browser Ruby on Rails Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 13. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Examples of metaprogramming Java compiler Ruby interpreter Firefox browser Ruby on Rails Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 14. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Examples of metaprogramming Java compiler Ruby interpreter Firefox browser Ruby on Rails Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 15. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Examples of metaprogramming Java compiler Ruby interpreter Firefox browser Ruby on Rails Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 16. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages def i s _ s t u f f _ c h a r ( c ) ( c >= ?a && c <= ?z ) | | ( c >= ?A && c <= ?Z ) | | ( c >= ?0 && c <= ?9) | | c == ?_ end def f i n d _ s t u f f ( s t r ) r e s u l t = [ ] ; i = 0 ; while i < s t r . l e n g t h s t a r t = i ; i += 1 while i s _ s t u f f _ c h a r ( s t r [ i ] ) i f s t a r t ! = i && s t r [ i ] == ’@’ a t = i ; i += 1 i += 1 while i s _ s t u f f _ c h a r ( s t r [ i ] ) r e s u l t << s t r [ s t a r t . . . i ] i f a t ! = i end ; i += 1 ; end r e s u l t ; end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 17. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages def f i n d _ e m a i l s ( s t r ) s t r . scan ( / w+@ w+ / ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 18. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages DSLs are everywhere Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 19. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages musical notes PP PPP PPP PPP P' DSLs are everywhere Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 20. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages guitar chords musical notes PP oo PPP ooo PPP ooo PPP o wooo P' DSLs are everywhere Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 21. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages guitar chords musical notes PP oo PPP ooo PPP ooo PPP o wooo P' DSLs are everywhere 7 nnn nn nnn nnn n traffic signs Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 22. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Domain specific languages guitar chords musical notes PP oo PPP ooo PPP ooo PPP o wooo P' DSLs are everywhereOOO gO 7 nnn OOO nn nnn OOO nnn OO n Ruby traffic signs Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 23. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 24. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Metaprogramming in Java public P l u g i n c r e a t e _ p l u g i n ( S t r i n g name , S t r i n g [ ] keys , S t r i n g [ ] v a l u e s ) throws . . . { Class c = Class . forName ( name ) ; Class s = Class . forName ( quot; [ L j a v a . l a n g . S t r i n g ; quot; ) ; C o n s t r u c t o r co = c . g e t C o n s t r u c t o r ( s , s ) ; r e t u r n ( P l u g i n ) co . newInstance ( keys , v a l u e s ) ; } Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 25. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Metaprogramming in Ruby def c r e a t e _ p l u g i n ( name , keys , v a l u e s ) O b j e c t . c o n s t _ g e t ( name ) . new ( keys , v a l u e s ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 26. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Comparison Metaprogramming in Ruby is easy Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 27. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary Comparison Metaprogramming in Java is hard Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 28. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , ’ v% ’ banks = c o n n e c t i o n . execute ( quot; SELECT b . name FROM customer AS c , bank AS b , account AS a WHERE ( c . f i r s t n a m e = ’ #{first1} ’ OR c . f i r s t n a m e = ’ #{first2} ’ ) AND c . lastname LIKE ’ #{last} ’ AND a . owner = c . i d AND a . bank = b . i d quot;) Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 29. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby : ActiveRecord Bank . f i n d ( : all , : i n c l u d e => { : accounts => : customer } , : c o n d i t i o n s => [ quot; ( customers . f i r s t _ n a m e = ? OR customers . f i r s t _ n a m e = ? ) AND customers . last_name LIKE ? quot; , quot; first1 quot; , quot; first2 quot; , quot; last quot; ] ) . map { | b | b . name } Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 30. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby : my own DSL f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , / Av / banks = query do from : c => Customer , : b => Bank , : a => Account s e l e c t b . name where ( ( c . f i r s t n a m e == f i r s t 1 ) | ( c . f i r s t n a m e == f i r s t 2 ) ) & ( c . lastname =~ l a s t ) & ( a . owner == c ) & ( a . bank == b ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 31. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby : my own DSL f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , / Av / banks = query do from : a => Account s e l e c t a . bank . name where ( ( a . owner . f i r s t n a m e == f i r s t 1 ) | ( a . owner . f i r s t n a m e == f i r s t 2 ) ) & ( a . owner . lastname =~ l a s t ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 32. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby : my own DSL f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , / Av / banks = query do from : a => Account c = a . owner s e l e c t a . bank . name where ( ( c . f i r s t n a m e == f i r s t 1 ) | ( c . f i r s t n a m e == f i r s t 2 ) ) & ( c . lastname =~ l a s t ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 33. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby A Ruby DSL is just plain Ruby Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 34. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby easy to build O OOO OOO OOO O' A Ruby DSL is just plain Ruby Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 35. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby easy to build familiar syntax O OOO n nnn OOO nnn OOO nn wnnn O' A Ruby DSL is just plain Ruby Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 36. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary DSLs in Ruby easy to build familiar syntax O OOO n nnn OOO nnn OOO nn wnnn O' A Ruby DSL is just plain O Ruby abstraction Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 37. Introduction Metaprogramming DSL implementation Ruby and Metaprogramming Summary What I’ll Teach You f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , / Av / banks = query do from : c => Customer , : b => Bank , : a => Account s e l e c t b . name where ( ( c . f i r s t n a m e == f i r s t 1 ) | ( c . f i r s t n a m e == f i r s t 2 ) ) & ( c . lastname =~ l a s t ) & ( a . owner == c ) & ( a . bank == b ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 38. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 39. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? self is the current object Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 40. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? instance variables OO OOO OOO OOO ' self is the current object Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 41. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? instance dotless variables OO methods n OOO n nnn OOO nnn OOO vnnn ' self is the current object Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 42. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? instance dotless variables OO methods n OOO n nnn OOO nnn OOO vnnn ' self is the current object 8 qqq q qqq qqq qq class variables Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 43. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? instance dotless variables OO methods n OOO n nnn OOO nnn OOO vnnn ' self is the current object 8 gOOO qqq O OOO q qqq OOO qqq O qq changed by class method calls, variables class defs Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 44. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? banks = query do ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 45. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? banks = s e l f . query do ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 46. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? # Top l e v e l p self # => main p s e l f . class # => O b j e c t Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 47. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators What is self? banks = s e l f . query do ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 48. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The Kernel module Kernel Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 49. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The Kernel module puts O OOO OOO OOO O' Kernel Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 50. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The Kernel module puts O raise OOO qqq OOO qqq OOO qq xqqq O' Kernel Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 51. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The Kernel module puts O raise OOO qqq OOO qqq OOO qq xqqq O' Kernel oo7 ooo ooo ooo require Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 52. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The Kernel module puts O raise OOO qqq OOO qqq OOO qq xqqq O' KernelMM fMMM oo7 ooo M ooo MMM ooo MM require eval Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 53. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators The query method module K e r n e l def query yield # C a l l the block end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 54. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do from : c => Customer , : b => Bank , : a => Account ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 55. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do s e l f . from : c => Customer , ... ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 56. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do p s e l f # => main end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 57. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do s e l f . from : c => Customer , ... ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 58. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self Sometimes we want to change self Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 59. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self class Query end module K e r n e l def query (& b l k ) Query . new . i n s t a n c e _ e v a l (& b l k ) end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 60. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do p s e l f # => #<Query : 0 xb7cc4adc > end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 61. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self instance_eval changes self for the duration of a block Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 62. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self class Query def i n i t i a l i z e @from = { } end def from (map) @from = map end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 63. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Changing self banks = query do from : c => Customer , : b => Bank , : a => Account p s e l f # => #<Query : 0 xb7cc4adc # @from = { : b=>Bank , : a=>Account , : c=>Customer } > end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 64. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 65. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading Rails can do lazy class loading Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 66. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading test.rb # r e q u i r e ’ brug ’ BRUG. new ( Time . now ) brug.rb class BRUG def i n i t i a l i z e ( t i m e ) @time = t i m e end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 67. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Constant lookup BRUG.new Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 68. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Constant lookup BRUG.new  n = Module.nesting + [Object] Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 69. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Constant lookup BRUG.new  n = Module.nesting + [Object]  find BRUG in n Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 70. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Constant lookup BRUG.new  n = Module.nesting + [Object]  find BRUG in n u u uu uu u founduuu uu uu uu uu zuu return BRUG Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 71. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Constant lookup BRUG.new  n = Module.nesting + [Object]  u KK find BRUGKin n u KK uu KK uu KK u founduuu KK found not KK uu KK uu KK uu KK uu KK zuu % n [0]. const_missing(:BRUG) return BRUG Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 72. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Module.nesting class A module B def m Module . n e s t i n g # => [ A : : B , A ] end Module . n e s t i n g # => [ A : : B , A ] end end Module . n e s t i n g # => [ ] def A .m Module . n e s t i n g # => [ ] end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 73. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading banks = query do from : c => Customer , : b => Bank , : a => Account p Module . n e s t i n g + [ O b j e c t ] # => [ O b j e c t ] ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 74. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy loading def O b j e c t . c o n s t _ m i s s i n g ( c i d ) f i l e = f i n d _ f i l e ( cid ) require f i l e const_get ( cid ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 75. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading def O b j e c t . c o n s t _ m i s s i n g ( c i d ) f i l e = f i n d _ f i l e ( cid ) require f i l e i f const_defined? cid const_get ( cid ) else # c a l l old const_missing end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 76. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading def O b j e c t . c o n s t _ m i s s i n g ( c i d ) f i l e = f i n d _ f i l e ( cid ) require f i l e i f const_defined? cid const_get ( cid ) else # Class < Module super end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 77. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Lazy class loading Lazy class loading is freakingly easy Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 78. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 79. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Handling b.name banks = query do ... s e l e c t b . name ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 80. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Handling b.name banks = query do ... s e l e c t s e l f . b . name ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 81. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Handling b.name class Query def b ... end end banks = query do ... s e l e c t s e l f . b . name ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 82. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Handling b.name Can we avoid mass method definition ? Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 83. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Missing methods self .b.name Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 84. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Missing methods self .b.name ww ww ww b foundwww w ww ww w ww {ww self .b.name Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 85. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Missing methods self .b.name J JJ ww JJ ww JJ ww JJ b foundwww J bJnot found w JJ ww JJ ww JJ w JJ ww J$ {ww self .method_missing(:b) self .b.name Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 86. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Query#method_missing banks = query do ... p s e l f # => #<Query : 0 xb7cf5dd4 > s e l e c t s e l f . b . name ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 87. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Query#method_missing class Query def method_missing ( mid , ∗ args ) i f args . l e n g t h == 0 && @from [m] V a r i a b l e E x p r e s s i o n . new (m) else super end end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 88. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Query#method_missing class V a r i a b l e E x p r e s s i o n < Expression a t t r _ r e a d e r : varname def i n i t i a l i z e ( varname ) @varname = varname end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 89. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Alternative implementation class Query a l i a s old_mm method_missing def method_missing (m, ∗ args ) i f args . l e n g t h == 0 && @from [m] V a r i a b l e E x p r e s s i o n . new (m) else old_mm (m, ∗ args ) end end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 90. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Expression#method_missing banks = query do ... # select b s e l e c t b . name ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 91. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Expression#method_missing class Expression def method_missing (m, ∗ args ) i f args . l e n g t h == 0 F i e l d E x p r e s s i o n . new ( s e l f , m) else super end end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 92. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing Expression#method_missing class F i e l d E x p r e s s i o n < Expression def i n i t i a l i z e ( expression , f i e l d ) @expression , @ f i e l d = expression , f i e l d end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 93. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Summary YES, we can avoid mass method definition Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 94. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Outline Introduction 1 Metaprogramming Ruby and Metaprogramming DSL implementation 2 Changing self Missing constants Missing methods Implementing custom operators Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 95. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Oerator overloading banks = query do ... where ( ( c . f i r s t n a m e == f i r s t 1 ) | ( c . f i r s t n a m e == f i r s t 2 ) ) & ( c . lastname =~ l a s t ) & ( a . owner == c ) & ( a . bank == b ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 96. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Operator overloading Operators are just methods Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 97. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Operator overloading banks = query do ... where ( ( c . f i r s t n a m e . = = ( f i r s t 1 ) . | ( c . firstname .==( f i r s t 2 ) ) . & ( c . lastname . = ~ ( l a s t ) . & ( a . owner == c ) . & ( a . bank . = = ( b ) ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 98. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing operator overloading class Expression def ==( o t h e r ) BinaryOpExpression . new ( s e l f , o t h e r , ’= ’ ) end def &( o t h e r ) BinaryOpExpression . new ( s e l f , o t h e r , ’AND ’ ) end ... end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 99. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Implementing operator overloading class BinaryOpExpression < Expression def i n i t i a l i z e ( expr1 , expr2 , op ) @expr1 , @expr2 , @op = expr1 , expr2 , op end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 100. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Limitations operator overloading &&, ||, ! are NOT methods Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 101. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Summary but ... Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 102. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Limitations operator overloading Operator overloading is child’s play Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 103. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Wrapping up the example banks = query do ... where . . . end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 104. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Wrapping up the example class Query def where ( cond ) @where = cond end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 105. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Wrapping up the example class Query def t o _ s q l quot;SELECT # { r e t u r n _ l i s t } quot; quot;FROM # { t a b l e _ l i s t } quot; quot;WHERE # { c o n d i t i o n _ e x p r } quot; end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 106. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Wrapping up the example class Query def t a b l e _ l i s t @from . map { | v , t | quot; # { t } AS # { v } quot; } . j o i n ( quot; , quot; ) end def r e t u r n _ l i s t @select . map { | r | r . t o _ s q l } . j o i n ( quot; , quot; ) end def c o n d i t i o n _ e x p r @where . t o _ s q l end end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 107. Changing self Introduction Missing constants DSL implementation Missing methods Summary Implementing custom operators Wrapping up the example f i r s t 1 , f i r s t 2 , l a s t = ’ p e t e r ’ , ’ glenn ’ , / Av / banks = query do from : c => Customer , : b => Bank , : a => Account s e l e c t b . name where ( ( c . f i r s t n a m e == f i r s t 1 ) | ( c . f i r s t n a m e == f i r s t 2 ) ) & ( c . lastname =~ l a s t ) & ( a . owner == c ) & ( a . bank == b ) end Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 108. Introduction DSL implementation Summary Summary Ruby has very natural metaprogramming facilities Ruby allows building DSLs in pure Ruby Metaporgramming made easy Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 109. Introduction DSL implementation Summary Summary Ruby has very natural metaprogramming facilities Ruby allows building DSLs in pure Ruby Metaporgramming made easy Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 110. Introduction DSL implementation Summary Summary Ruby has very natural metaprogramming facilities Ruby allows building DSLs in pure Ruby Metaporgramming made easy Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 111. Introduction DSL implementation Summary Further reading why’s (poignant) guide to Ruby http://poignantguide.net/ruby/ http://poignantguide.net/ruby/chapter-6.html Ruby for Rails http://www.manning.com/black/ Programming Ruby http://www.rubycentral.com/pickaxe/ http://www.pragmaticprogrammer.com/title/ruby/ Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 112. Introduction DSL implementation Summary Further reading why’s (poignant) guide to Ruby http://poignantguide.net/ruby/ http://poignantguide.net/ruby/chapter-6.html Ruby for Rails http://www.manning.com/black/ Programming Ruby http://www.rubycentral.com/pickaxe/ http://www.pragmaticprogrammer.com/title/ruby/ Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 113. Introduction DSL implementation Summary Further reading why’s (poignant) guide to Ruby http://poignantguide.net/ruby/ http://poignantguide.net/ruby/chapter-6.html Ruby for Rails http://www.manning.com/black/ Programming Ruby http://www.rubycentral.com/pickaxe/ http://www.pragmaticprogrammer.com/title/ruby/ Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby
  • 114. Introduction DSL implementation Summary REAL Summary Ruby rocks!!! Peter Vanbroekhoven peter@xaop.com Metaprogramming in Ruby