Skip to content

Alternative strawman #20

Open
Open
@dead-claudia

Description

@dead-claudia

I decided to take a bit to sketch out an alternative strawman, to see what I could do. Key takeaways:

  • Coming up with a concise, well-defined syntax and semantics set is hard. As if that wasn't already obvious, though... 😄
  • I had to create an additional implicit context channel to avoid this conflicting issues. It was much better than introducing this footgun: forEach(array) do (item) { this.consume(item) }.
  • I had to figure out a better system to solve the scoping issue, and I decided to settle on no sigil on top-level DSLs, @ for dependent DSLs, and tentatively :: for top-level control flow DSLs and : for dependent control flow DSLs. I know the former could conflict with decorators and the latter with labels, but I made mention of how to address it (as in, decorators and labels come first, respectively).
  • Managing control flow is incredibly hard, even at the conceptual level. It's bad enough to just incorporate synchronous, immediate values into the mix, but add the ability to suspend the context, and I quickly had to jump to coroutines, just to have a sane execution model for the DSLs themselves.
  • Managing completions without reifying them is pretty difficult to come up with solutions for. It wasn't exactly a simple thought process to go from reified completions to just using syntax. I used try/catch as a base because they already deal with abrupt completions.
  • I tried dealing with the exact completions in the spec when modeling the control flow DSLs, but I found a few complications and glitches with that reasoning (and why I opted to model my "inline completions" based on outside behavior instead):
    • break could mean the DSL itself, or it could mean an outer loop.
    • continue is really just a glorified block-level return, so there's little point in discerning them.
    • return breaks out of the loop and triggers the same exit sequence as break does.
    • throw can work a lot like return, but it can also just be an error handleable by the DSL itself.
    • Sometimes, you want to short-circuit and return a value for the DSL's callee, like in the select example here in this repo's README. This can't be modeled with a completion in terms of the current spec.

Here's a few other features specific to my rendition:

  • The implicit scope is accessible, and I do make it possible to read from and write to members of the context, to make it much more transparent and user-friendly.
  • I also took into account the possibility of computed properties, and tried to support that use case.
  • I found it easier to treat control flow arguments as thunks, and similarly, I made the syntactic variant use call-by-name, rather than call-by-value.

/cc @samuelgoto @rwaldron

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions