soma.cell

E0081: lambda_scope

E0081 lambda_scope — a lambda reads a name that is not in scope where it runs.

A compile-time error of soma check, the checker of the Soma programming language (soma explain E0081).

The rule

A lambda captures only the locals bound before it, so a lambda that calls itself (or a lambda bound later in the block) cannot see that name; check refuses it rather than letting it fail at run time. For recursion write a handler, on walk(k: Int) { ... }, which can call itself.

A program that triggers it

wrong.cell

cell Countdown {
    on total_steps(n: Int) {
        let walk = k => if k <= 0 { 0 } else { k + walk(k - 1) }
        return walk(n)
    }
}

What soma check prints:

$ soma check wrong.cell
error: the lambda `walk` calls `walk`, which it cannot see: a lambda captures the locals bound before it — for recursion write a handler (`on walk(…)`)
  --> wrong.cell:3:20
  |
3 |         let walk = k => if k <= 0 { 0 } else { k + walk(k - 1) }
  |                    ^
  = code: E0081
✗ 1 error(s), 0 warning(s).

The fix field of soma check --json: for recursion write a handler (`on walk(…)`)

4 lines are added after line 1; line 3 is removed.

wrong.cell → right.cell

--- wrong.cell
+++ right.cell
@@ -1,5 +1,8 @@
 cell Countdown {
+    on walk(k: Int) {
+        if k <= 0 { return 0 }
+        return k + walk(k - 1)
+    }
     on total_steps(n: Int) {
-        let walk = k => if k <= 0 { 0 } else { k + walk(k - 1) }
         return walk(n)
     }

With the fix, soma check accepts the program:

$ soma check right.cell
✓ All checks passed.