Domain-Specific Language
- Rule-based
- Pattern-matching
- Very dull to read
Example: turn the monitor background color green
Ruby execution: turn (the (monitor (background (color (green) ) ) ) )
turn the monitor background color green
=code dsl_part_1.rb
turn the monitor background color "green"
=code dsl_part_2.rb
How do we execute the code inside this object?
@dsl_object.color green
"green" is evaluated within the current scope, so unless it's a variable, it doesn't exist
Ruby uses message passing
@dsl_object.send("color green")
Oh yeah, some guy named Irb says "color green"
Hmmm, do I have a method named "color green"? Nope.
Hmmm, do my ancestors have "color green"? Nope.
Ooh, I know! self.method_missing("color green")
@dsl_object.send("color green") => "color green"
Two ways:
=code instance_eval.rb
turn the monitor background "#00FF00"
=code dsl_part_3.rb
turn the monitor ["background","#00FF00"]
No additional code needed here!
turn the ["monitor","background","#00FF00"]
=code dsl_part_4.rb
turn ["monitor","background","#00FF00"]
=code dsl_part_5.rb
Example: turn the beat around
=> turn ["beat","around"]
Where's the third argument?
Example: Set course for the Hoth system
Any issues?
(Hint: You CAN type this into IRB without error)
Set course for the Hoth system
- Set, Hoth => Constant undefined
- for => reserved word
- system => already defined (inherited from Object)
We can fix most of these!
=code blank_slate.rb
Two DSLs:
-
Represent the environment
-
Interpret user input
=code bad_text_adventure.rb
=code bad_text_adventure_english.rb
=code better_text_adventure.rb
=code better_text_adventure_english.rb
=code better_text_adventure_indented.rb
=code world.rb
=code location.rb
=code player.rb
-
Preprocess the input
-
Provide a context to execute
-
Manipulate the environment
=code game.rb
=code runner.rb
Thanks!