Why Call-Site Type Arguments Exist¶
This page explains the design intent behind explicit call-site type arguments (f[T](...), obj.m[T](...)).
For exact syntax and rules, see:
The problem this solves¶
Incan normally infers generic type parameters from value arguments.
That works well when value arguments fully constrain type parameters.
It breaks down when one or more type parameters are underconstrained at the call site, or when inference picks a type that is valid but not what you intend.
Common case: APIs where row/model type matters for downstream typing, but value arguments (like file paths) do not uniquely pin that type.
What explicit call-site arguments add¶
Call-site type arguments let the caller lock the generic instantiation directly.
Definition side:
class Session:
def read_csv[T](path: str) -> List[T]:
...
Caller side:
rows = session.read_csv[Order]("orders.csv")
read_csv[T] defines a generic contract: “for any T, return List[T]”.
read_csv[Order](...) specializes that contract at the call site, so rows is typed as List[Order].
This keeps normal signature typing intact while letting callers pin ambiguous generic slots at API boundaries.
Why _ exists¶
Sometimes you only care about one slot and want the rest inferred.
Definition side:
def validate_rows[T, E](rows: List[T]) -> Result[List[T], E]:
...
Caller side:
a = validate_rows[Order, _](rows) # pin T, infer E
b = validate_rows(_, RuntimeError)(rows) # pin E, infer T
Here T is fixed to Order, while E is left as _ and inferred.
This avoids forcing callers to spell every type argument when only one slot needs pinning.
_ keeps partial explicitness concise while preserving arity checks.
What this feature is not¶
- It does not replace normal function/method signatures (
def f(x: T) -> Uremains the default form). - It does not require callers to always be explicit.
- It does not provide overload-based "optional static/dynamic entrypoint" behavior by itself. That route belongs to RFC 028-style overloading design.
Practical guidance¶
- Prefer inference by default.
- Use explicit call-site args when API boundaries or readability benefit from locking the type.
- Use
_when only some type parameters need to be pinned.