Ruby DSL Handbook
clean-ruby.com
clean-ruby.com
Signed: everyone who's ever used a DSL which could have been written better as a couple of dozen functions.
I had /some/ bad experiences with some DSL, but most of my experiences with them were pretty good (even those who I didn't write).
I can't remember the joke but the tagline goes, "Code I didn't write" anyone?
Ruby is a really bad language to write good DSLs in. Metaprogramming is an awkward replacement for better DSL facilities.
Maybe this book can demonstrate better techniques?
I find that metaprogramming in Ruby is a tremendous hack for getting something like syntax abstraction and something like control over evaluation order. Personally, syntax abstraction doesn't feel super important for deep or shallow embedded DSLs (though it's obvious a big deal in external DSLs if you want to walk that minefield). You need more than nothing, but making it "human language like" is ridiculous.
Controlling flow is a big part of it though. Ruby's block syntax does a lot here, but frankly functions/abstractions never feel first class in Ruby---only Objects do and Objects are too heavyweight.
DSLs should be looked at as syntactic sugar for object instantiation. Language methods should set the object's state or run an instance method. Object behavior goes in the object's class.
I'm looking at one of my DSLs, it's a module with a parse method that takes a file with a default argument to the common "XXXXfile" that I see used a lot for DSLs. It opens the file and module_eval's the code. I use instance and module variables to hold state in the execution context of the DSL.
If you stick to this pattern you'll find a DSL easy to manage. I use it as a replacement for instantiating objects with YAML files, which I find brittle. I hate maintaining those, but a DSL will give me just the right amount of indirection. I can express the objects exactly how I want them to be expressed, which is a big win for me.
http://www.infoq.com/presentations/kilmer-ruby-dsls
Good stuff from a guy who's done some pretty massive DSLs on DARPA projects.
attr_reader foo
The 'foo' above would evaluate to the contents of the variable 'foo'. So, you have to do this: attr_reader :foo
Because we cannot control how this code evaluated, we must quote 'foo'. This greatly limits what we can express. [:foo, :bar].each do |attribute|
attr_reader attribute
end
You probably wouldn't want do actually do that with attr_reader, but it is just an example.No, it would not be nice. It would be in violation with basic ruby syntax.
If that is the best example you could come up with then I'm glad ruby does not allow whatever it is that you're asking for.
But this isn't about regular Ruby syntax, this is about extending Ruby syntax by embedding new languages within it. A new language may have new evaluation rules. As another user points out, there's a syntax called 'alias' that works similarly to my example, so I disagree that it would be violating anything.
>I'm glad ruby does not allow whatever it is that you're asking for.
I'm essentially asking for macros commonly found in the Lisp family of languages.
That's an unfortunate wart on the language (an inconsistency) and not related to your example at all.
I'm essentially asking for macros commonly found in the Lisp family of languages.
Can you come up with a real-world use case for that?