Skip to content

Uniform function call syntax

Allow an eligible free-function call f(x, y, ...) to be written in receiver form x.f(y, ...), preserving the resolved callable while exposing a uniform chainable surface syntax.

Version
v2 · 2026-08-30 · History
Domain-specific #
3031
Origin domain
programming language design
Subdomain
call syntax and name resolution

Core Idea

Uniform function call syntax is a language rule under which an eligible free function whose first parameter accepts an expression can be invoked using that expression as the apparent receiver, making x.f(y) resolve as f(x,y) under the language's stated rules.[1] Parsing produces receiver-form syntax, resolution first handles any precedence mandated for real members, then searches eligible free functions and type-checks the receiver as the first argument; chaining feeds each result into the next call.

Its autonomous residual is the specified receiver-to-first-argument call equivalence and resolution contract, not method invocation in general, dynamic dispatch, extension-method metadata, or pipelines with different evaluation rules. The identity fails when the language only permits members, the apparent method is a separately declared extension member, lookup changes the callable silently, argument order differs, or dot notation merely accesses a field containing a function.

Recognition requires an analyst to quote the language specification, identify lookup and precedence rules, expand receiver form to the equivalent ordinary call, verify overload selection and evaluation order, and separate convenience syntax from ownership or dispatch semantics. Once established, it supports fluent call chains, discoverable operations, generic programming over free functions, reduced pressure to add nonessential members, and explicit analysis of ambiguities between members and extensions without turning those uses into the definition.

Structural Signature

  • Carrier: a language implementation with free functions, receiver-form calls, typed or otherwise constrained name resolution, and a declared UFCS rewrite or lookup rule
  • Inputs or antecedent state: a receiver expression, candidate function name, remaining arguments, scopes or imports, overload set, applicability rules, and member-versus-free-function precedence
  • Constitutive operation: Parsing produces receiver-form syntax, resolution first handles any precedence mandated for real members, then searches eligible free functions and type-checks the receiver as the first argument; chaining feeds each result into the next call
  • Invariant: the receiver notation and ordinary free-function notation can designate the same callable and argument ordering when the language's eligibility and resolution conditions are met
  • Recognition test: quote the language specification, identify lookup and precedence rules, expand receiver form to the equivalent ordinary call, verify overload selection and evaluation order, and separate convenience syntax from ownership or dispatch semantics
  • Output or consequence: fluent call chains, discoverable operations, generic programming over free functions, reduced pressure to add nonessential members, and explicit analysis of ambiguities between members and extensions
  • Failure boundary: the language only permits members, the apparent method is a separately declared extension member, lookup changes the callable silently, argument order differs, or dot notation merely accesses a field containing a function

What It Is Not

  • It is not the whole field of programming language design; many objects in that field do not satisfy its constitutive rule.
  • It is not its canonical example. In D, if an applicable member does not exist and an in-scope free function sun accepts x as its first argument, x.sun(1) can resolve as sun(x,1). That is an instance, not a definition.
  • It is not Function-Level Programming. Function-level programming combines whole programs through program-forming operations; UFCS is a language surface and resolution rule for expressing particular calls, not a composition algebra over programs.
  • It is not an unrestricted metaphor. D, Nim, Koka, Effekt, Lean, and proposals for C++ differ in lookup, member precedence, ambiguity handling, templates, and whether authors themselves use the UFCS label

Scope of Application

Uniform function call syntax applies when the analyst can specify a language implementation with free functions, receiver-form calls, typed or otherwise constrained name resolution, and a declared UFCS rewrite or lookup rule and establish that the receiver notation and ordinary free-function notation can designate the same callable and argument ordering when the language's eligibility and resolution conditions are met. The entry describes specified language behavior and design consequences; it does not recommend one language style or promise equivalence across languages with different lookup rules.[2]

  • Recognition. quote the language specification, identify lookup and precedence rules, expand receiver form to the equivalent ordinary call, verify overload selection and evaluation order, and separate convenience syntax from ownership or dispatch semantics
  • Comparison. Compare legitimate instances through lookup scope, real-member precedence, first-argument compatibility, overload resolution, type inference, imports, templates, evaluation order, chaining, ambiguity, and diagnostics.
  • Boundary. D, Nim, Koka, Effekt, Lean, and proposals for C++ differ in lookup, member precedence, ambiguity handling, templates, and whether authors themselves use the UFCS label
  • Use. Preserve every assumption when using the identity for fluent call chains, discoverable operations, generic programming over free functions, reduced pressure to add nonessential members, and explicit analysis of ambiguities between members and extensions.

Clarity

A clear claim names the carrier, governing rule, assumptions, and recognition test. This matters because uniform can mean syntactic equivalence, unified lookup, or merely a documentation convention, so the exact rewrite and resolution rule must be stated. The disciplined statement is that the object counts as Uniform function call syntax exactly when the receiver notation and ordinary free-function notation can designate the same callable and argument ordering when the language's eligibility and resolution conditions are met

Identity and measurement remain separate. Readability and discoverability claims require human evidence, while semantic equivalence is checked against the language specification and compiler behavior. Approximation or noisy evidence may weaken a classification without changing its definition.

Manages Complexity

The abstraction compresses D UFCS, Nim method-call syntax, functional-language receiver forms, proposed C++ unified calls, static and dynamic typing, and IDE completion behavior into a stable carrier, rule, invariant, and failure boundary. It makes comparison tractable while retaining the variables that control validity.

Compression can hide assumptions. A responsible use therefore declares lookup scope, real-member precedence, first-argument compatibility, overload resolution, type inference, imports, templates, evaluation order, chaining, ambiguity, and diagnostics and returns to the full diagnostic whenever a convention or boundary case changes.

Abstract Reasoning

  1. Type the carrier. Establish a language implementation with free functions, receiver-form calls, typed or otherwise constrained name resolution, and a declared UFCS rewrite or lookup rule and reject examples from a different problem.
  2. Lock the rule. Express that the receiver notation and ordinary free-function notation can designate the same callable and argument ordering when the language's eligibility and resolution conditions are met independently of one notation or implementation.
  3. Derive carefully. Infer fluent call chains, discoverable operations, generic programming over free functions, reduced pressure to add nonessential members, and explicit analysis of ambiguities between members and extensions only under the stated assumptions.
  4. Stress-test. Contrast the legitimate boundary case—D, Nim, Koka, Effekt, Lean, and proposals for C++ differ in lookup, member precedence, ambiguity handling, templates, and whether authors themselves use the UFCS label—with this counterexample: Rust's fully qualified syntax can invoke a trait method through an explicit path but does not thereby permit every free function to be written as a method call.

Knowledge Transfer

Transfer within programming language design is strong when new cases preserve the same carrier, mechanism, and diagnostic. The move from In D, if an applicable member does not exist and an in-scope free function sun accepts x as its first argument, x.sun(1) can resolve as sun(x,1). to A sequence transformation can be written as chained receiver-form calls even when each stage is implemented as a free function. demonstrates that continuity.[3]

Outside the domain, only the skeleton—offer a second notation that preserves an underlying operation while foregrounding one argument as the access point—travels automatically. The terms free function, member function, receiver, first argument, overload resolution, name lookup, extension method, chaining, pipeline, and syntactic sugar retain domain-specific meanings, so every role and inference must be revalidated.

Examples

Canonical

In D, if an applicable member does not exist and an in-scope free function sun accepts x as its first argument, x.sun(1) can resolve as sun(x,1). The equivalence concerns call syntax and lookup; it does not make sun part of x's class, grant private access, or introduce virtual dispatch. It is canonical because the carrier, rule, invariant, and consequence are all inspectable.[1]

Mapped back: a language implementation with free functions, receiver-form calls, typed or otherwise constrained name resolution, and a declared UFCS rewrite or lookup rule → Parsing produces receiver-form syntax, resolution first handles any precedence mandated for real members, then searches eligible free functions and type-checks the receiver as the first argument; chaining feeds each result into the next call → the receiver notation and ordinary free-function notation can designate the same callable and argument ordering when the language's eligibility and resolution conditions are met → fluent call chains, discoverable operations, generic programming over free functions, reduced pressure to add nonessential members, and explicit analysis of ambiguities between members and extensions

Applied / In Practice

A sequence transformation can be written as chained receiver-form calls even when each stage is implemented as a free function. Each intermediate result becomes the next first argument, but type compatibility and evaluation behavior remain governed by the ordinary function calls. It qualifies only after the same diagnostic and failure boundary are checked.[2]

Mapped back: declared instance → recognition test → boundary check → qualified use

Structural Tensions

  • T1: Exact identity vs. practical recognition. The constitutive condition may be exact while evidence is indirect. Diagnostic: Can the reviewer state both the condition and the warrant?
  • T2: Canonical form vs. variants. D UFCS, Nim method-call syntax, functional-language receiver forms, proposed C++ unified calls, static and dynamic typing, and IDE completion behavior can preserve or change the identity. Diagnostic: Which named role is invariant across the variants?
  • T3: Compression vs. hidden assumptions. The label is useful only while prerequisites remain visible. Diagnostic: Can each downstream inference be traced to a declared assumption?
  • T4: Autonomy vs. reduction. The candidate uses broader structures but claims the specified receiver-to-first-argument call equivalence and resolution contract, not method invocation in general, dynamic dispatch, extension-method metadata, or pipelines with different evaluation rules. Diagnostic: Does that residual still support independent recognition after the parent and neighbors are subtracted?

Structural–Framed Character

The entry is structurally mixed but domain-framed. Its portable skeleton is offer a second notation that preserves an underlying operation while foregrounding one argument as the access point; its identity-bearing terms are free function, member function, receiver, first argument, overload resolution, name lookup, extension method, chaining, pipeline, and syntactic sugar. Those terms determine admissible objects, evidence, and consequences inside programming language design.

Structural Core vs. Domain Accent

The structural core is a carrier governed by Parsing produces receiver-form syntax, resolution first handles any precedence mandated for real members, then searches eligible free functions and type-checks the receiver as the first argument; chaining feeds each result into the next call and tested by quote the language specification, identify lookup and precedence rules, expand receiver form to the equivalent ordinary call, verify overload selection and evaluation order, and separate convenience syntax from ownership or dispatch semantics. The domain accent is constitutive rather than decorative, so an analogy that preserves only the skeleton is not another instance of Uniform function call syntax.

The proposed strict upward parent is prime:representation. UFCS literally provides an alternate surface representation of the same callable relation and argument order; language-specific parsing and lookup supply the residual. The edge is proposal-only and points to a frozen prior-baseline Prime.

The entry does not collapse into the parent because the specified receiver-to-first-argument call equivalence and resolution contract, not method invocation in general, dynamic dispatch, extension-method metadata, or pipelines with different evaluation rules A thematic neighbor is declined whenever it does not literally subsume that rule.

The prospective workspace queue contains one strict upward edge to prime:representation. No live DAG mutation is authorized.

Relationships to Other Abstractions

Local relationship map for Uniform function call syntaxParents appear above the current abstraction, mutual partners to the right, and children below. Node labels state whether each abstraction is prime or domain-specific; colors identify relation types.Uniform functioncall syntaxDOMAINPrime abstraction: Representation — is a kind ofRepresentationPRIME

Current abstraction Uniform function call syntax Domain-specific

Parents (1) — more general patterns this builds on

  • Uniform function call syntax is a kind of Representation Prime

    The proposed strict upward parent is prime:representation.

Hierarchy path (1) — routes to 1 parentless root

Neighborhood in Abstraction Space

Uniform function call syntax sits in a moderately populated region (53rd percentile for distinctiveness): it has near-neighbors but no dense thicket of look-alikes.

Family — Syntax, Rewriting & Declarative Form (41 abstractions)

Nearest neighbors

Computed from structural-signature embeddings · 2026-09-08

Not to Be Confused With

  • Method call. Invokes an actual member or dynamically dispatched operation; UFCS may resolve a nonmember free function.
  • Extension method. Usually attaches external method-like declarations through language metadata rather than a general first-argument rewrite.
  • Pipeline operator. Feeds a value through a dedicated operator whose precedence and argument insertion rules can differ.
  • Fully qualified syntax. Disambiguates a declared method or trait item and need not support free-function receiver notation.

References

[1] D Language Foundation, D Programming Language Specification, 'Functions,' §26 Uniform Function Call Syntax, current edition, 2026, https://dlang.org/spec/function.html#pseudo-member. registry ↩a ↩b

[2] Nim Project, Nim Manual, 'Method call syntax,' current stable manual, 2026, https://nim-lang.org/docs/manual.html#procedures-method-call-syntax. registry ↩a ↩b

[3] Herb Sutter, 'Unified function call syntax (UFCS),' ISO/IEC JTC1/SC22/WG21 paper P3021R0, 2023, https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p3021r0.pdf. registry