What Is "Open Recursion"?

Open recursion explained, and devs kick off a cross‑language cage match

TLDR: A clear explainer shows “open recursion” as methods calling other methods on the same object while honoring overrides. Comments erupted into a language showdown: praise for dynamic dispatch, shade at C’s rigidity, and Go called out for “fake inheritance,” proving this concept decides how your code actually behaves.

A dev accidentally wrote a whole explainer on “open recursion” — the idea that object methods can call other methods on the same object and still respect overrides — using a friendly Dart example. Think: defining all the buttons in one go so they can press each other. The crowd loved the clarity, with glhaynes cheering, “This was really helpful,” while Akronymus sparked a mini-seminar by asking if the example used closures or just names glued to code. Cue a chorus of “explain it like I’m five” and a couple of nerdy fist bumps to Pierce’s TAPL and Essentials of Compilation.

Then the language wars broke out. chubot declared open recursion just feels “natural” in Python/Java/C++/Rust, with C singled out as the strict parent that won’t allow late-night dynamic dispatch. skybrian crashed the party with a spicy Go take: Go’s “struct embedding” looks like inheritance but secretly refuses self-overrides — a bait-and-switch that had Go fans posting “it’s not a bug, it’s a feature” memes. Meanwhile, kazinator went low-level, flexing a garbage collector example where the system hands control back to the object’s own method — nerds calling it the “GC is open for business” moment. Bottom line: the post demystified the term, but the comments turned it into a cross‑language reality show about who really does “self” calls right.

Key Points

  • The term “open recursion” is introduced by Benjamin C. Pierce in Types and Programming Languages.
  • The article models object behavior using a subset of Dart with functions and maps, without classes or methods.
  • Implementing methods that call each other fails in Dart due to lack of function hoisting and declaration ordering issues.
  • Mutually recursive definitions are needed so methods can reference each other simultaneously (e.g., letrec in Scheme/ML).
  • C achieves similar mutual visibility via forward declarations, illustrating cross-language mechanisms for recursion-friendly bindings.

Hottest takes

"the only language I use that doesn’t have such late binding/dynamic dispatch is C" — chubot
"Struct embedding gives you the syntax of inheritance... but for internal self-calls, methods don’t get overridden" — skybrian
"Example of open recursion: add a new object type into a low-level language run time" — kazinator
Made with <3 by @siedrix and @shesho from CDMX. Powered by Forge&Hive.