ADR-002: Multi-method signatures for CAN and DOES predicates

Status

Proposed

Context

The current _CLASSCAN, _INSTANCECAN, _INVOCANTCAN, _CLASSDOES, and _INSTANCEDOES predicates accept exactly one method or role name ($$ prototype).

In practice, callers often need to verify that an invocant satisfies multiple capabilities at once (e.g. "provides both connect and disconnect") or fulfils several roles simultaneously. Today this requires chaining multiple calls:

_INSTANCECAN($obj, 'connect') and _INSTANCECAN($obj, 'disconnect')

This is verbose and evaluates the blessed/class check repeatedly.

Decision

Deferred. Introduce multi-method variants once a concrete consumer demonstrates the need. The design space includes:

Signature change

_INSTANCECAN($obj, @methods) -- breaks the $$ prototype. Prototypes cannot express $@, so the function would need to drop its prototype or use a different calling convention.

Semantic: AND vs OR

Multiple arguments most naturally mean "provides all of these" (AND). An OR semantic ("provides at least one") is a different use case and would warrant a separate function name to avoid ambiguity.

XS implications

A variadic XS implementation must loop over the method list in C, calling ->can or ->DOES for each. The early-exit on first failure makes this efficient, but the stack handling differs from the current fixed-arity pattern.

Interaction with Assert (ADR-003)

An assertion variant that reports which method is missing benefits from knowing the full list up front rather than failing on the first chained call.

Consequences

  • No action required now; the $$ variants are sufficient for the initial release.

  • When a consumer emerges, the multi-method variant should be added as a new function name (e.g. _INSTANCECAN_ALL) rather than changing the existing $$ signature, preserving backwards compatibility.

  • The same pattern applies to _CLASSDOES / _INSTANCEDOES for verifying multiple roles simultaneously.