views:

131

answers:

1

Coming from Ruby to Javascript, creating DSL now seems not as fun as in Ruby where it was very beautiful and elegant.

Ruby Rake:

task :hello do
   # do stuff
end

task :hello => [:dep1, :dep2] do
   # do stuff
end

Javascript Jake:

task("hello", function() {
   // do stuff
});

task("hello", ["deep1", "deep2"], function() {
   // do stuff
});

But why don't we use the powerful object literals instead:

Javascript Jake with Json:

task({
   name: "hello",
   action: function() {
      // do stuff
   }
});

task({
   name: "hello",
   dependencies: ["deep1", "deep2"],
   action: function() {
       // do stuff
   }
});

I think this is much more appropriate to create DSL cause it is at the same time a configuration syntax.

When I started to use Sproutcore that is using this kind of configuration design I thought this should be the way Javascript is doing configuration/DSL. Cause now you can save the configurations in the database or send them back and forth between frontend and backend because they are only object literals. Maybe also pass these configuration to frameworks in other languages.

I think it's easier to see what is doing what, than just passing a bunch of arguments, and it's very structural. With this you could also put all the keys out there in the beginning so the programmer/non-programmer could fill them in:

task({
    // name: "",
    // type: "",
    // dependencies: [],
    // action: function() {},
    // callback: function() {}
});

vs:

task(
   // "",
   // "",
   // [],
   // function() {},
   // function() {}
);

With object literals you could also do nesting:

task({
   name: {
      base: "",
      extension: "",
   },
   children: [
      "",
      "",
   ],
});

In this way Javascript DSL could be easier to use than Ruby DSL imho. I think the above examples show which one if more graspable at first look.

I don't know if arguments are meant for doing configurations. Using object literals (hashes/arrays) seems to me more appropriate imo.

Isn't it better to use object literals than arguments to create DSL?

EDIT: I used Jake/Rake just to have something I could use for examples. It's nothing towards these frameworks specifically. It's meant for enlightning the differences between configuration with arguments vs with object literals.

+5  A: 

The only real difference between passing arguments and using an object literal is that with normal arguments, you pass them directly but must specify them in a particular order, while with an object, you pass them surrounded by curly braces and must put a label before each value. This fails to rival the expressivity of even Ruby's pseudo-DSLs (much less an actual DSL), and is really just a labeled argument syntax akin to Python's.

So the "Why not?" is "It imposes an awkward calling convention and likely slowdown for modest benefit." The "Why do it?" is "It lets me label arguments in the code as opposed to the documentation or IDE support." It's not unquestionably bad, but it also imposes a bloat penalty (particularly if you include every possible key even when it's not being defined to anything) and varying levels of awkwardness since Javascript isn't really designed for this, so it's not questionably good either. It's a design decision.

As for your assertion that "I don't know if arguments are meant for doing configurations": It depends on what you mean. A function's parameters by definition are meant to affect the behavior of the function. So in that sense they're "configuring" the function. But at the same time, passing an entire 500-value preferences file as arguments to a function is not sensible, because the function will not actually act on all those arguments in a meaningful way.

Chuck