cd /news/developer-tools/e-the-middle-ground-between-english-… · home topics developer-tools article
[ARTICLE · art-54710] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

E‑‑: The middle ground between English and Python

A developer introduced E--, a programming language that allows developers to dial the ratio of English to Python per line. The language uses {{...}} slots for English descriptions resolved by an LLM at compile time, producing deterministic Python code. E-- aims to combine the readability of English with the precision of code, offering a middle ground between natural language and traditional programming.

read7 min views1 publishedJul 10, 2026

Or, what if you could dial how much English lives in your code, per line?

Modern LLM code generation has a strange property. Your program's behavior is a function of your prompt, the model's mood, and whatever context happened to be in memory. There's no single artifact you can point to and say "this is what runs." Same input, different output. Same request, different code.

You can work around this — cache LLM output, freeze model versions, forbid regeneration at runtime. But you're always working around the LLM, never with it.

E-- flips the shape. What if the LLM's involvement was constrained to a specific structural slot in your source, resolved once at compile time, and everything else was normal deterministic code? Now you can pick, per value, how much LLM you want in your program. Once picked, the result is byte-for-byte reproducible.

You can dial the English-Python ratio per line, per value, per region. Whichever end of the spectrum makes sense right there.

Here's the same intent expressed at three different points on the dial.

Fully coded — you commit to every value:

Set tempo to 70.
Set piece to Call [[compose_blues]] with tempo=tempo, key="E".
Return piece.

Mixed — structure is code, one value is English:

Set tempo to {{ a tempo appropriate for a slow blues }}.
Set piece to Call [[compose_blues]] with tempo=tempo, key="E".
Return piece.

More English — most of the intent is described, not written:

Set piece to {{ compose a slow blues in E with a tempo appropriate for the style }}.
Return piece.

Same intent. Different English-Python ratios. Author chose.

The {{ ... }}

markers are slots — placeholders where you write English instead of a value. E-- treats them as first-class syntax. At compile time, the compiler resolves each slot to a concrete Python expression. Then normal deterministic code runs.

E-- has a closed grammar of English-ish verbs: Define

, Set

, Let

, Do

, Call

, Return

, Give back

, For each

, If

, Otherwise

. Statements end in a period. Function references appear as [[wikilinks]]

.

A canonical program:

Define [[describe]] taking n:
    If n is greater than 10:
        Give back "big".
    Give back "small".

For each n in <3, 42, 7>:
    Do [[print]]([[describe]](n)).

Compiles to:

def describe(n):
    if n > 10:
        return "big"
    return "small"
for n in [3, 42, 7]:
    print(describe(n))

Verb-first, sentence-shaped, but structured enough to parse deterministically. Reads out loud like English.

A slot is a {{ ... }}

placeholder containing an English description. At compile time, the compiler dispatches an LLM to resolve the slot to a concrete Python expression.

Value slots — the simplest case:

Set tempo to {{ a tempo appropriate for a slow blues }}.

The compiler asks the LLM: "convert 'a tempo appropriate for a slow blues' to a Python expression." LLM returns 70

. Compiler splices it in. Final code: tempo = 70

.

Code slots (v0.2.0) — for whole regions:

Set tempo to 70.
{{ create a harmony using form with the tempo }}
Set piece to Call [[voices_list]] with sections=[harmony].
Return piece.

The slot at line 2 is at a statement position — the compiler asks the LLM to produce statements (plural), which get spliced in at proper indentation.

Resolution is a one-time cost. The compiler caches every slot resolution keyed by the slot's text. Subsequent builds are cache hits — no LLM call, byte-identical output. Once your slots are resolved, the resulting Python is a normal deterministic artifact you can inspect, run, share, freeze, whatever.

Accessibility meets precision. Programming languages have historically had to pick. English-like DSLs (Inform 7, AppleScript, SQL) traded expressiveness for readability. Full programming languages trade readability for expressiveness. E-- doesn't force the choice: use precise syntax where you know what you want; use English where you'd rather describe. Both on the same line if you want.

Domain experts can code the parts they know. A musician writes structural composition — call these functions, in this order, combine them. They defer specifics — key, tempo, scale characteristics — to English descriptions. Same for a biologist authoring a simulation: fix the experimental structure, let the LLM pick reasonable parameters. Same for a designer, a hobbyist, a student.

Runtime is deterministic and cheap. Because slot resolution happens at compile time and gets cached, no LLM call ever happens at runtime. Same source, same behavior forever. Cost scales with authoring, not execution.

Programs are inspectable at multiple levels. You have the source (structured, human-readable, English-y), the resolved intermediate (still E--, slots now filled), and the compiled Python. Three artifacts you can look at when things break. Traditional LLM-generated code gives you only the natural-language input and the (possibly regenerated) output — the intermediate structure has evaporated. Debug that: you've got a bug you can't reproduce, in code you didn't write, on a system that costs you an API call to inspect.

Static analysis is easy on structured code. Chip palette insertion, dependency graph extraction, wikilink navigation — all straightforward on E-- syntax. Trade-off: inside a code slot, the resolved code is opaque to structural tooling. You choose per-slot whether structure or delegation matters more.

E-- exists because a project called Forge needed a language its cohort could author.

Forge is an environment for creative work — music composition, generative art, running simulations — where non-programmers author computable notes. The cohort's users are musicians, artists, researchers. Python was inaccessible. Description-only was imprecise. E-- filled the middle.

Every note has three facets: a Description in prose, a Recipe in E--, and the compiled Python. All three are visible in the editor at once.

Here's a Recipe for a 12-bar blues:

Let harmony = Call [[form]].
Let drums = Call [[drum_chorus]] with profile="standard".
Let guitar = Call [[guitar_solo_chorus]].
Let piece = Call [[voices_list]] with sections=[harmony, drums, guitar].
Return piece.

form

, drum_chorus

, guitar_solo_chorus

, voices_list

are library functions in Forge's music library. The Recipe composes them like building blocks.

That Recipe transpiles to Python which constructs the musical score (via music21) and renders it as MusicXML in the user's editor. Once the Recipe is written, everything downstream is deterministic. Two users open the same note and get the same blues.

A more advanced user might write a Recipe with slots:

Let tempo = {{ a tempo appropriate for a slow blues }}.
Let key = {{ a key that pairs well with a moody vocal style }}.
Let piece = Call [[compose_blues]] with tempo=tempo, key=key.
Return piece.

They know the structure — compose a blues, at some tempo, in some key. Specifics they'd rather delegate. LLM resolves once at compile time; result caches; subsequent renders are pure.

Forge is one consumer. E-- itself is a language substrate any system could build on. If you want your users to author programs that are precise enough to run but accessible enough to read — with escape hatches to English wherever they want them — E-- is a shape that works.

Try it in 30 seconds:

pip install e-minus-minus

Then a tiny E-- program:

printf 'Set x to 5.\nDo [[print]](x).\n' > hello.emm
emm-transpile hello.emm

Prints:

x = 5
print(x)

That's it. No LLM required for canonical E-- with no slots. See the README for slot resolution and free-English input.

E-- itself:

pip install e-minus-minus

Forge (an example consumer):

Get in touch:

If you're building a tool that could use E--, if you have questions about the design, or if you'd like to collaborate on where the language goes next — email me at ** frmoded@gmail.com**. E-- is small and open-source (Apache 2.0). If you use it in your own project, let me know what you build.

── more in #developer-tools 4 stories · sorted by recency
── more on @e-- 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/e-the-middle-ground-…] indexed:0 read:7min 2026-07-10 ·