openlang

A small punctuation request can reach three language layers

Partly reviewed

Suppose authors of an embedded rule language request age>=18=>allow without spaces or parentheses. The visual change is small. Deciding where it belongs requires asking which layer recognizes the pieces before any rule runs.

In Racket, the reader establishes the initial syntax representation. Under ordinary reading, that fragment can arrive as a symbol rather than the sequence of operators its author imagines. A macro could deliberately parse the symbol's spelling, but that would be a little parser inside the notation. It would not redefine the lexical conventions surrounding the macro. A custom reader is appropriate when the language actually needs different token boundaries or delimiter rules.

Expansion has another job. Given recognized syntax, it can reject malformed rule forms, establish bindings and translate a rule into calls. Runtime code must still obtain an age value, decide what happens when it is absent and perform any permitted action. If the notation later adds an attempt form, expansion may arrange a call to a retry engine. Whether that engine repeats a test, an action or both needs a runtime contract.

A named language can package the reader and expander starting points when these choices form a coherent authoring environment. That also creates documentation and tooling obligations. If the request merely means calling an existing comparison and returning a decision, a plain library call may already express it clearly. I would justify the additional boundary through the rules authors need to read and maintain.

The conversation continues 2

Follow the reasoning
  1. Permalink

    Your proposed attempt form needs to expose whether its body can run again. In a Clojure version of that form, suppose expansion puts a Ref update and a notification call inside dosync. A conflict can repeat the body while only one state change commits, so the notification may repeat. Attractive punctuation cannot supply that missing effect contract. Returning notification data for later delivery separates the attempts from the effect, but the language still owes callers a delivery policy.

  2. Permalink

    A missing threshold also tests your division between expansion and runtime. Suppose a runtime rule evaluator signals a condition and offers a replacement-value restart. The caller may know the appropriate threshold. A handler-bind handler can invoke that restart while the signaling context remains available. Returning normally instead declines handling. A handler-case clause runs after control transfers and unwinding, so it is a different recovery arrangement. The notation should document which choices survive.