Open Recursion¶
A shared object method calls through its current receiver so specialized receiver behavior can determine the internal call's target.
Core Idea¶
Open recursion allows shared object behavior to invoke another operation on the current receiver, with the target selected using that receiver's specialized behavior. A base method can thereby invoke a subclass override; a method found through delegation can send to the original child receiver. The shared method does not have to name the eventual target in advance.[1][2]
The relation relies on the same receiver being available inside the shared method and a lookup or dispatch rule that can select a specialization. The term describes self-reference in an extensible object structure; one execution need not call itself repeatedly or terminate through a base case.
How would you explain it like I'm…
Do Your Own Version
Calling Your Own Special Version
Late-Bound Self Dispatch
Structural Signature¶
- Shared method: behavior provided by a base class or parent object.
- Current receiver: the object on which the outer operation runs.
- Internal self-send: the shared method invokes an operation on that receiver.
- Receiver-sensitive lookup: dispatch can choose a specialized target for that same receiver.
- Variation: a receiver's override or supplied method changes the target without editing the shared method.
- Boundary: language rules decide which calls permit this dispatch.
What It Is Not¶
An arbitrary virtual call to another object is dynamic dispatch but does not establish an internal self-send. A fixed private or explicitly directed base call does not exhibit the same receiver-sensitive interception. The selection of JavaScript this at a call site is a separate receiver-binding question.
Scope of Application¶
Class-based overriding and prototype-style delegation can each implement this pattern. The exact dispatch rules, available specializations, and treatment of private, static or explicit-super calls depend on the language.
Clarity¶
Separating the outer method's location from its receiver explains why an inherited method can invoke behavior defined by a more specific object.
Manages Complexity¶
A shared operation can be reused while an accessor or hook changes. This localizes customization but can make internal implementation choices observable to subclasses.
Abstract Reasoning¶
Ask what happens if the same shared method runs on a different compatible receiver: a change in the selected internal target demonstrates the dispatch role. A method that sends only to a fixed helper does not pass that test.
Knowledge Transfer¶
The same question helps compare class overrides and delegation without assuming their object models or source syntax are identical.
Examples¶
CountingSet and a changed base method¶
Aldrich's CountingSet overrides add and addAll; the latter invokes the base addAll and increases its counter by the collection size. If the base implementation is changed to call add per element, the internal calls dispatch on the same CountingSet receiver to its overriding add, incrementing the counter a second time. This is the paper's hypothetical implementation change, not a documented production incident.[1]
Mapped back: shared method Set.addAll; receiver the subclass instance; internal operation add; selected target CountingSet.add. Aldrich's proposed selective scheme makes non-open internal calls static while leaving external calls dynamically dispatched.
Delegating points¶
In Tanter's teaching system a point parent supplies add, whose body sends x? to self. random-point delegates to point and supplies x? as a random computation. A send of add to random-point uses the shared parent method while its internal x? resolves to the child. The example's random output is not a fixed prediction; the notation is the teaching system's, not Self syntax.[2]
Mapped back: shared method point.add; receiver random-point; internal operation x?; target the child accessor. Binding lookup to the parent alone would not find an accessor on this parent, an inference from the presented definitions. Ungar and Smith separately describe a related Self point design.[3]
Structural Tensions¶
The CountingSet example shows a concrete tradeoff: interception offers extension yet exposes a base implementation choice to a subclass. This is a risk in the illustrated design, not an inevitable defect of every open call.[1]
Structural–Framed Character¶
The structural relation is receiver-preserving extensible lookup, independent of the particular point or set. Its language and evaluation arise in programming design: openness can be valuable for extension and costly for encapsulation depending on intent. The vocabulary travels among object models, while its origin and practical meaning are tied to programming language design. A reader recognizes the pattern in an existing method arrangement rather than importing the name as a prerequisite. Its character: a structural mechanism framed by programming practices and design choices.
Structural Core vs. Domain Accent¶
The portable core is shared behavior referring back to an extensible receiver. Receiver identities, method lookup, class overrides and delegation are programming-specific realizations. Recursive descent reduces a problem through smaller cases toward a base case; open recursion does not necessarily do either. This named mechanism remains specific to receiver-oriented programming.
Instantiates / Related Primes¶
Inheritance captures default transfer and override along a lineage; it does not by itself require an internal self-send. Open recursion may arise in the class case or through delegation, so the present comparison does not establish a necessary typed parent.
Neighborhood in Abstraction Space¶
Open Recursion sits in a sparse region of the domain-specific corpus (98th percentile for distinctiveness): few abstractions share its structure, so a faithful description tends to retrieve it precisely.
Family — Unclustered & Miscellaneous (2835 abstractions)
Nearest neighbors
- Yo-yo Problem — 0.79
- Object-Oriented Programming — 0.76
- Virtual function — 0.75
- Feature Envy — 0.74
- Current-instance receiver reference — 0.74
Computed from structural-signature embeddings · 2026-10-31
Not to Be Confused With¶
- Receiver binding: selecting which object
thisdenotes answers a different question from how a subsequent internal method call is dispatched. - Ordinary recursive descent: repeated reduction to a base case is not required here.
- All dispatch: selection for an unrelated receiver lacks the same-receiver role.
References¶
[1] Jonathan Aldrich, “Selective Open Recursion A Solution to the Fragile Base Class Problem”, figure 1 and §§1.1–2, directly inspected PDF text. registry ↩a ↩b ↩c
[2] Éric Tanter, “Forwarding and Delegation,” Object-Oriented Programming Languages: Application and Interpretation, §§4.3.2 and 4.4, directly inspected online textbook. registry ↩a ↩b
[3] David Ungar and Randall B. Smith, “Self The Power of Simplicity”, Lisp and Symbolic Computation 4, no. 3 (1991), §3 and figure 4, printed pp. 8–9, directly inspected PDF text and caption; figure layout not independently visually inspected. registry ↩