ADR-049: The Automatic a, b, c Are Withdrawn

Status: Superseded by ADR-277 — its D1 is D2 there; D2 is not carried (the timing of the withdrawal, done) Related: ADR-041 (which made naming the arguments the normal form, carried these as experimental and warned about them; this completes it), ADR-022 (the other lambda form this language withdrew, and the precedent for withdrawing one), ADR-024 (NK1117, which is what refuses the form now without a rule of its own).

1. Context

A lambda could be written with no parameter list at all — fn { a.id } — and its arguments were three fixed names, a, b, c.

The rule underneath it is the problem, not the spelling. How many arguments such a lambda takes was read off which of the three names its body mentions. So a local called a inside one was not a local: it was an argument, and a body that wrote let c = … was asking for a third one.

ADR-041 made that visible: naming the arguments became the normal form, the automatic names were carried as experimental, and NK1114 warned wherever one was actually reached for. Visible is not the same as good. The rule stayed true for exactly as long as the form existed, and every lambda in the language depended on it.

2. Decisions

D1 — The three automatic names are withdrawn. fn { … } takes no arguments.

A lambda’s arguments are the ones it names. A lambda that names none takes none, which is the form .or_insert_with fn { Stats(0) } wants and has always meant.

Refused, not warned about. What goes with the form is the rule underneath it: the arity-from-body mechanism, NK1114, and the one function the emitter and the checker shared to compute it. Left in place they would keep the rule alive.

And it needs no refusal of its own. A body reaching for a is a body naming something nothing declares, which is NK1117 — the check that exists because this language has no word it does not know. So the withdrawal removes code and adds none.

D2 — Not announced a release ahead.

Announcing a withdrawal one release before making it is the procedure for a language with code in the world. There is no release and no Nikaia outside this repository, so a deprecation window protects nobody — and what it would do is keep both the rule and the warning alive for the length of the window.

3. Consequences

Eight sites in four programs are rewritten, in two idioms: folding into a map entry (.and_modify fn (stats) { stats.add(m.temp) }) and a sort key (.sort_by_key fn (row) { -row.1 }). They had to be, since after this they do not compile.

What it costs is a named argument where a letter used to do. That is the whole of it, and the name is usually better: fn (stats) { stats.add(m.temp) } says what is being added to.

The specification loses a form rather than gaining a warning. Part I 5.3 was two options with the second marked experimental; it is one form now, and the withdrawn one is described in a paragraph that says why.

4. What this does not decide

Whether a short form should exist in future, in either direction. This is about these three names and the rule that came with them, not about brevity.

A count of the lambdas in this repository was offered as evidence for that question and is withdrawn as worthless: it omitted the parameter list from the comparison it was making, and twenty-one lambdas written by the language’s own authors say nothing about how anybody else would write.

5. What is built

All of it, and as a removal.

Expr::Closure has no implicit flag: the parser produces the same node for fn { … } and fn () { … }, both with no parameters. emit::implicit_params — the one function the emitter wrote its parameter list from and the checker asked whether to warn — is gone, and so is check::warn_automatic_names and the NK1114 code. The checker pushes the parameters a lambda names and nothing else, so a body reaching for a meets NK1117.

NK1114’s number is retired rather than reused, and Part III C.3 says so: a code that meant something in a published specification should not come back meaning something else.

examples/1brc.nika, examples/access-log/src/main.nika, examples/k-nucleotide/src/main.nika and examples/inventory/src/main.nika name their lambda arguments, as do the specification’s own examples.

This site is open source. Improve this page.