Predicate Dispatch¶
A guarded method-selection mechanism that tests arguments for applicability and, in its formal form, orders applicable implementations by predicate implication.
Core Idea¶
Predicate dispatch selects one implementation of a generic operation using conditions on the arguments of a particular call. Each candidate method carries a guard: a predicate stating when that implementation applies. The formal predicate-dispatch model evaluates applicability and lets a method with guard \(p\) override one with guard \(q\) when \(p\) logically implies \(q\). Thus the narrower applicable guard can win without requiring a hand-written ladder of tests inside the operation.[1][2]
The two questions must be kept separate. Does a guard hold for these actual arguments? is a run-time applicability question. Does one guard imply another for every possible argument? determines a formal override relationship and can require static reasoning about a whole predicate language. Rich guard syntax does not make implication automatically decidable; implementations such as JPred restrict predicates and use decision procedures for the relationships they promise to check.[2]
Receiver-class dispatch and multimethod type dispatch fit the formal scheme when their class tests are expressed as predicates. Predicate dispatch can additionally select on a field value, state or relationship among arguments. That expressive gain creates a coherence obligation: if two guards both hold but neither implies the other, the formal order has no unique most-specific winner unless the language defines a further rule or rejects the program.[1][2]
Structural Signature¶
Sig role-phrases: shared generic call; guarded method bodies; argument-specific applicability; implication-based override in the formal model; coverage and ambiguity check; concrete-language rule boundary.
- Generic operation: one invocation has several candidate implementations.
- Guarded implementations: each body is paired with a condition on receiver, arguments or their relationships.[1]
- Call-specific applicability: actual arguments determine which guards hold.
- Override or selection order: in the formal model, logical implication orders applicable guards; concrete languages may instead use a restricted or different rule.
- Coverage and coherence: the design must handle no applicable method, several incomparable applicable methods, or a unique winning method. JPred checks exhaustion and unambiguity for its supported predicate language.[2]
Condensed: shared operation + guarded alternatives + applicability test + specified specificity rule = predicate dispatch.
What It Is Not¶
- Not merely an if-chain. A branch inside one method can have similar outcomes, but guarded implementations make applicability and overriding part of the dispatch system rather than local body control flow.
- Not only virtual-function dispatch. Receiver-class selection is a restricted case in the formal account; value and relationship predicates can also matter.[1]
- Not unrestricted decidable reasoning over arbitrary code. A run-time guard may be executable while implication between two arbitrary programs remains undecidable. Practical static checking needs a restricted language, conservative approximation or another policy.[2]
- Not guaranteed ambiguity-free. Overlap between incomparable guards is a real hazard; a system needs rejection, an explicit priority rule or another specified resolution.
- Not equivalent to every language's guarded multi syntax. Raku permits `where` clauses, but its official documentation says declaration order can settle some `where` and `subset` cases. That is related guarded dispatch, not evidence of formal implication ordering in every case.[3]
- Not predicate abstraction. That neighboring technique constructs an abstract state space from predicates; it is not itself the rule for selecting a method body.
Scope of Application¶
In the original formal account, applicability predicates may inspect argument classes, subcomponents, states and relationships. A type-only dispatch table is expressible by guards such as “the first argument is an instance of class \(C\),” whereas a state-sensitive case can add “its status field equals ready.” The narrower guard should override the broader one only when implication follows from the declared semantics, not merely because it looks more specialized to a reader.[1]
JPred is a practical Java-language example. Its methods include predicate guards; its compiler reasons about implication and checks whether methods cover possible calls without ambiguous winners. The paper uses a restricted predicate syntax and off-the-shelf decision procedures, not unrestricted equivalence testing of arbitrary Java expressions. Its modular checking has constraints; one should not infer universal open-world extension or zero-cost evaluation from the existence of guards.[2]
Raku multis with `where` constraints are a useful adjacent case for seeing argument-dependent applicability. They also mark a boundary: selection-order details do not automatically mirror the Ernst–Kaplan–Chambers implication relation. An encyclopedia comparison should state the concrete language rule rather than treating all guarded multi-dispatch systems as identical.[3]
Clarity¶
Suppose a generic operation handles a record. One method accepts every record; another accepts records whose state is `ready`; a third accepts records whose urgency is `high`. For a ready, high-urgency record, both specialized guards hold. Neither “ready” nor “high urgency” implies the other, so these two methods are incomparable under implication. A method guarded by ready and high urgency would imply both and could be their unique more-specific winner; absent such a method, a formal implication-order dispatcher must address ambiguity.
This is different from testing the guards in textual order and taking the first match. Textual order always supplies a tie-breaker, but it may choose a different implementation when methods are reordered; formal implication instead asks whether one method's accepted-call set is contained in another's.
Manages Complexity¶
Guarded methods localize cases that would otherwise be nested in a central dispatcher. The selection relation makes extension compositional only when new guards fit coherently with old ones. Static checks, where supported, shift some no-match and overlap failures from call time to compilation. The cost is reasoning about predicate relationships: a more expressive guard language can make completeness and specificity harder to decide.[2]
Abstract Reasoning¶
For a proposed call, list each method's guard and evaluate which are true. For each pair of applicable guards, test the language's actual precedence rule. In the formal model, draw \(p\to q\) when \(p\) implies \(q\); a unique most-specific applicable node is the selected method. If two maximal nodes are incomparable, investigate whether the program is rejected, a disambiguating method exists, or the language has a different tie-breaker. Separately ask whether at least one guard holds for every permitted call.[1][2]
The crucial diagnostic is: Does the selection system know why one applicable guard outranks another, or is it merely relying on declaration order?
Knowledge Transfer¶
The broad idea is guarded selection among alternatives. Its programming-language identity is specific: methods or functions are invoked, predicates inspect actual arguments, and an override or ambiguity policy chooses executable code. Analogies to policy engines and rule systems are useful only after their matching and precedence rules are stated; sharing “conditions” alone does not make them predicate dispatch.
Examples¶
Source-attested one.world discovery-service rewrite¶
Millstein's JPred case study rewrites event handlers in the one.world discovery service. Its `DiscoveryClient` `MainHandler` dispatches on the client's state and an event; a later example distinguishes a null `entry` from nonnull and branches on an `AnnounceEvent` capacity comparison. These are predicate properties of data, not merely receiver classes. The paper reports that converting 20 methods exposed an ambiguity/redundancy, three potential nonexhaustive cases and 11 unprotected casts. These findings are compiler/case-study observations, not a blanket guarantee that all predicate systems detect all errors.[2]
Mapped back: generic call = event handling; guarded bodies = state/event, null and capacity cases; applicability = properties of actual event/entry at a call; selection/coherence = JPred's restricted predicate implication and type checking; failure boundary = ambiguous or uncovered cases surfaced during this particular rewrite.
Constructed implication lattice¶
For a `handle(record)` operation, take a fallback guard `true`, one guard `ready`, another `highUrgency`, and a fourth `ready && highUrgency`. For a record satisfying both properties, all four apply; the conjunction implies each single-property guard and is the unique most-specific choice. Remove that fourth method and the two single-property guards remain incomparable despite both applying. This is a constructed logic illustration, not source code from JPred.[1]
Mapped back: generic call = `handle`; guards = four predicates; applicable set = all four for the joint-state record; ordering = logical implication; selected body = conjunction method; counterfactual = without it, the formal order has no unique winner.
Incomparable overlap¶
“Ready” and “high urgency” methods both accept a record satisfying both conditions. Neither guard alone implies the other. Unless an intersecting guard or a documented tie-breaker supplies a winner, the call is ambiguous in the formal implication order.
Mapped back: applicability without unique specificity.
Structural Tensions¶
Expressiveness versus decidable static checking. A richer predicate language lets methods select on more state and relationships, but implication, ambiguity and coverage checks become harder or unavailable. JPred restricts its guards so useful checks can run, and the case study notes a disjunction/binding idiom that its restriction rejects. Diagnostic: which desired guard pattern is lost to obtain sound modular checks?[2]
Open extension versus preserved coherence. Adding a new guarded method can extend behavior without editing existing bodies; if its guard overlaps an incomparable existing one, an old call may become ambiguous or change winner. Restricting extensions or requiring a disambiguating conjunction preserves coherent dispatch but costs some independent extension freedom. Diagnostic: does the new guard imply, exclude or incomparably overlap the old applicable guards?[1][2]
Structural–Framed Character¶
Predicate dispatch is mostly structural as a method-selection mechanism: a call, guarded alternatives, applicability and an override rule determine a body. Its evaluative weight as “safer” or “more extensible” depends on what a language can check and how programs evolve, as JPred's one.world rewrite illustrates without proving universal safety. Human language-design practice fixes the guard grammar and ambiguity policy; compiler implementations and programming-language research establish which static guarantees are available. The term arose in dispatch theory and travels literally to a language when conditions are method guards with an explicit selection semantics. Calling an ordered `if` chain or a Raku `where` multi automatically the Ernst–Kaplan–Chambers implication calculus imports a rule not established for that construct. Its character: a guarded method-dispatch mechanism whose formal implication order is precise but whose practical checking and precedence are language-specific.[1][2][3]
Structural Core vs. Domain Accent¶
The portable skeleton is guarded alternative selection with a precedence relation; live Selection is the accepted compositional prerequisite of each dispatch invocation, not the taxonomic genus of the persistent method mechanism. The domain-bound mechanism is invocation of multiple implementations of one generic operation, guards over arguments and states, and an override/ambiguity policy that determines executable code. The named entry fails the prime bar because firewall rules, medical triage and ordered prose conditions can also have guards and precedence without being method dispatch; removing calls, bodies and language semantics loses its identity. Formal implication distinguishes one important predicate-dispatch account from looser guarded-language relatives, so the specific ordering should not be projected into every neighbor.
Instantiates / Related Primes¶
This entry presupposes Selection.
Selection is the compositional prerequisite: an invocation differentially admits and chooses among guarded executable methods. Predicate dispatch is a persistent language mechanism, not itself one selection event; ordinary Selection need not involve methods or an implication ordering. Concrete tie-breaking and decidability vary by language.
Relationships to Other Abstractions¶
Current abstraction Predicate Dispatch Domain-specific
Parents (1) — more general patterns this builds on
-
Predicate Dispatch presupposes Selection Prime
Each predicate-dispatch invocation differentially admits and chooses applicable methods under guarded selection.The staged bearer is a guarded method-selection mechanism and language-level dispatch rule. Each invocation tests candidate methods against predicates and differentially admits or prefers alternatives, so it necessarily executes live Selection. The whole persistent dispatch mechanism is not identical to an individual selection operation; composition/presupposes preserves the mechanism/operation distinction. Ordinary selection needs no methods or predicate-implication order.
Hierarchy path (1) — routes to 1 parentless root
- Predicate Dispatch → Selection
Neighborhood in Abstraction Space¶
Predicate Dispatch sits in a sparse region of the domain-specific corpus (65th percentile for distinctiveness): few abstractions share its structure, so a faithful description tends to retrieve it precisely.
Family — Type Systems & Functional Constructs (18 abstractions)
Nearest neighbors
- Modus ponens — 0.85
- Long Parameter List — 0.85
- Command–query separation — 0.84
- Denying the Antecedent — 0.84
- Principle of Explosion — 0.84
Computed from structural-signature embeddings · 2026-10-08
Not to Be Confused With¶
Multiple Dispatch usually resolves by run-time types across arguments; it is representable within the formal predicate framework but not the entire framework. Virtual Function typically dispatches from receiver type. Pattern Matching can have ordered clauses, which need not share implication-based override. Predicate Abstraction is a state-space abstraction technique, not method selection. Raku `where` multis are a guarded-dispatch variant whose ordering semantics require separate documentation.[1][3]
References¶
[1] Ernst, Kaplan and Chambers, “Predicate dispatching: A unified theory of dispatch” (ECOOP 1998), author-hosted abstract of the original theory. registry ↩a ↩b ↩c ↩d ↩e ↩f ↩g ↩h ↩i ↩j
[2] Millstein, “Practical Predicate Dispatch” (OOPSLA 2004), original JPred paper, especially abstract, introduction, predicate-language figure and static-checking discussion. registry ↩a ↩b ↩c ↩d ↩e ↩f ↩g ↩h ↩i ↩j ↩k ↩l
[3] Official Raku documentation, “multi”, dispatch and declaration-order qualifications for `where` and `subset`. registry ↩a ↩b ↩c ↩d