samuelgoto / proposal-block-params

A syntactical simplification in JS to enable DSLs
205 stars 8 forks source link

Why do so many examples use {}s? #21

Open domenic opened 6 years ago

domenic commented 6 years ago

E.g.

let data = survey("TC39 Meeting Schedule") {
  question("Where should we host the European meeting?") {
    option("Paris") {}
    option("Barcelona") {}
    option("London") {}
  }
}

why doesn't this just use statements for the options, e.g. as in

let data = survey("TC39 Meeting Schedule") {
  question("Where should we host the European meeting?") {
    option("Paris");
    option("Barcelona");
    option("London");
  }
}

?

This probably has to do with some of the restrictions on the contents of the blocks, which are not really spelled out (or maybe I skimmed over them too fast).

samuelgoto commented 6 years ago

This probably has to do with some of the restrictions on the contents of the blocks, which are not really spelled out (or maybe I skimmed over them too fast).

Yep, that's exactly the case: it has to do with how we deal with nesting: how do you make some block params to be connected to each other (i.e. in this example, survey is a parent of question which is a parent of option).

To a larger extent, this is really large question that is being raised in many forms (example).

@erights's suggestion (which I thinking I'm coming to terms with) is to require a explicit sigil (e.g. ::) to connect these things. In this formulation, instead of the { } at the end that you are seeing here, we would have something like a :: in the front to make a reference to the parent. Example:

let data = survey("TC39 Meeting Schedule") {
  ::question("Where should we host the European meeting?") {
    ::option("Paris");
    ::option("Barcelona");
    ::option("London");
  }
}

Would be transpiled to:

let data = survey("TC39 Meeting Schedule", (__parent__) => {
  __parent__.question("Where should we host the European meeting?", (__parent__) => {
    __parent__.option("Paris");
    __parent__.option("Barcelona");
    __parent__.option("London");
  })
})

Which would give survey to define what can go inside it (e.g. question) and question to define what can go inside it (e.g. option). For example:

function survey(name, block) {
  let survey = {question: []};
  block({
    question(name, inner) {
      let q = {name: name, options: []};
      survey.questions.push(q);
      inner({
        option(name) {
          let opt = {name: name};
          q.options.push(opt);
        }
      })
    }
  })
  return survey;
}

WDYT?

domenic commented 6 years ago

That seems reasonable, although it's becoming a bit syntactically heavy.