samuelgoto / proposal-block-params

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

Toss the nested block param idea #43

Open theScottyJam opened 2 years ago

theScottyJam commented 2 years ago

The whole :: idea is intriguing, but in the end, it really doesn't provide much value to the language, nor is it an essential part of the core concept of being able to pass blocks as arguments into functions.

The reason why it doesn't provide much value is because it's trivial to make an API that doesn't rely on it. Let me just pull some examples from the README, and show how I can build a very similar looking thing without the :: syntax:

/* map */

// before
let a = map {
  ::put("hello", "world") {}
  ::put("foo", "bar") {}
}

// after
let a = map($ => [
  $.put("hello", "world"),
  $.put("foo", "bar"),
])

/* custom data */

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

// after
let data = survey("TC39 Meeting Schedule", $ => [
  $.question("Where should we host the European meeting?", $ => [
    $.option("Paris"),
    $.option("Barcelona"),
    $.option("London"),
  ]),
])

/* kotlin's templates */

// before
let body = html {
  ::head {
    ::title("Hello World!") {}
  }
  ::body {
    ::div {
      ::span("Welcome to my Blog!") {}
    }
    for (page of ["contact", "guestbook"]) {
      ::a({href: `${page}.html`}) { span(`${page}`) } {}
    }
  }
}

// after
let body = html($ => [
  $.head($ => [
    $.title("Hello World!")
  ]),
  $.body($ => [
    $.div($ => [
      $.span("Welcome to my Blog!")
    ]),
    ...["contact", "guestbook"].map(page => (
      $.a({href: `${page}.html`}, $ => [$.span(`${page}`)])
    )),
  ]),
])

// Alternative that's more imperative and closer to the "before" example
let body = html($ => {
  $.head($ => {
    $.title("Hello World!")
  })
  $.body($ => {
    $.div($ => {
      $.span("Welcome to my Blog!")
    })
    for (page of ["contact", "guestbook"]) {
      $.a({href: `${page}.html`}, $ => $.span(`${page}`)}
    }
  })
})

Notice how similar the "before" and "after" are? You may disagree here, but I actually prefer the "after" versions. The "before" examples are imperative in nature (because they're built on blocks), and make the API user describe their desired piece of data by building it through a series of discrete steps. The "after" versions are declarative in nature, and simply showcase the desired data in it's entirety, with the help of some pure functions.

Anyways, the point is, I think it's hard to make a case for the "::" syntax and ask for it to pass the high syntax bar that EcmaScript has, when it's pretty trivial (and even arguably better/easier) to just build your APIs without it.