Live data from Hacker News

Ruby DSL Handbook

clean-ruby.com

21–30 of 30 posts

Re: Ruby DSL Handbook

#21
post #8
post #6

Earlier quoted context omitted.

Almost any problem can be meaningfully and usefully solved by introduction of a DSL. It's a remarkably flexible technique. 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?

Interesting, that runs counter to the prevailing sentiment that Ruby's metaprogramming makes it great for writing DSLs. What language features do you prefer for writing DSLs?

Typing, phantom typing, straightforward lambdas, sum types, tail-recursion, direct syntax abstractions (both Lisp and Idris are great examples).

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.

Re: Ruby DSL Handbook

#22
post #6

Earlier quoted context omitted.

Almost any problem can be meaningfully and usefully solved by introduction of a DSL. It's a remarkably flexible technique. 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?

Isn't the DSL just an ad-hoc implementation of a rules engine in many cases?

Can be. I see a lot of those, but rules engines are far from the only denotation of a DSL. It just tends to be that people want DSLs to be sort of natural language which drives people to end up with something like predicate logic which drives people to end up with something like Prolog and then you might as well have a rules engine.

Re: Ruby DSL Handbook

#23

I think it needs a foreword: "your problem likely is nowhere near needing a DSL, please don't write one just because it makes you look clever". Signed: everyone who's ever used a DSL which could have been written better as a couple of dozen functions.

I should someday make a screencast showing how I use DSLs in my projects. I've done the "couple dozen functions" thing enough times to know it only goes so far, whenever I find myself reaching for a DSL, I'd wished I'd done it sooner.

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.

Re: Ruby DSL Handbook

#24

Earlier quoted context omitted.

Let's use 'attr_reader' as a simple example. It defines a method that returns the value of a member variable. It would be nice to refer to the variable name literally, but this is not possible: 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 w…

That's one of the things I like about Ruby DSLs. Because the DSL is just Ruby, you can do things like: [: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.

Typically, you'd write syntactic sugar on top of regular functions, so that the underlying API is available in the host language to do things like in your example. Using Ruby's class syntax as an example, it gives you a convenient means to describe classes, but underneath that is an API for programmatic manipulation of class objects.

Re: Ruby DSL Handbook

#25

Earlier quoted context omitted.

This surprises me. Can you offer an example of those types of problems in some Ruby code?

Let's use 'attr_reader' as a simple example. It defines a method that returns the value of a member variable. It would be nice to refer to the variable name literally, but this is not possible: 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 w…

It would be nice to refer to the variable name literally

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.

Re: Ruby DSL Handbook

#26

I think it needs a foreword: "your problem likely is nowhere near needing a DSL, please don't write one just because it makes you look clever". Signed: everyone who's ever used a DSL which could have been written better as a couple of dozen functions.

I'm the author. In fact, the first bit of advice I have in the book is: Don't. DSLs often involve metaprogramming, but they don't have to. I'm writing it to record the code practices that I have found useful in getting things right and gather advice and tips from others who have done the same. DSLs are always about communication, so my goal is to create a book that helps developers communicate the purpose of the aspe…

Spoiler: the second bit of advice is "Step 2: No, seriously. Don't"

Re: Ruby DSL Handbook

#27

Earlier quoted context omitted.

Let's use 'attr_reader' as a simple example. It defines a method that returns the value of a member variable. It would be nice to refer to the variable name literally, but this is not possible: 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 w…

Ah. I see. That Ruby doesn't afford this can be somewhat annoying. A counter example is using "alias". It can accept bare words, symbols, or strings. If you really wanted to get around this you could use method_missing on the class but that can open a can of worms.

'alias' is special syntax in Ruby. This emphasizes my point: You, as the user of Ruby, do not have the power that the language designers have. You cannot create new syntax rules. I argue that this power is a necessary component for creating true EDSLs, but in practice the term is used much more loosely.

Re: Ruby DSL Handbook

#28
post #25

Earlier quoted context omitted.

Let's use 'attr_reader' as a simple example. It defines a method that returns the value of a member variable. It would be nice to refer to the variable name literally, but this is not possible: 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 w…

It would be nice to refer to the variable name literally 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.

>It would be in violation with basic ruby syntax.

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.

Re: Ruby DSL Handbook

#29
post #25

Earlier quoted context omitted.

It would be nice to refer to the variable name literally 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.

>It would be in violation with basic ruby syntax. 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 aski…

there's a syntax called 'alias' that works similarly to my example

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?

Re: Ruby DSL Handbook

#30
post #9

Earlier quoted context omitted.

That you suffered from DSL is probably a sign that this book will be filling a gap :-) 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).

"most of my experiences with them were pretty good (even those who I didn't write)." - lol, gotta love programmer arrogance, I'm guilty as well. I can't remember the joke but the tagline goes, "Code I didn't write" anyone?

Arrogance here is more caused by my bad english :-) I use more DSL that other people wrote, than mine.
Post reply on HN