Anton,

Thank you for taking the time to respond.
This is really helpful feedback, and I genuinely think the distinction
you're drawing is an important one to get right.

I think the parallel with Stringable holds more closely than it might seem.
If we put them side by side:

   - Both are automatically implemented by the engine for classes that
   define the corresponding magic method.
   - Both can be explicitly implemented by users.
   - Both enforce the presence of a magic method. Stringable enforces
   __toString(), Invokable enforces __invoke().
   - The argument that magic methods are just implementation details holds
   true for both.

The only difference is that __toString() has a fixed signature, so
Stringable can enforce it through a normal interface declaration.
__invoke() doesn't
have a fixed signature, so Invokable uses an enforcement handler instead.
Different mechanism, same contract. The difference is caused by the
variable signature, not by any fundamental difference in what the interface
represents.

The comparison to Throwable is interesting, but as far as I understand (and
please correct me if I am wrong), Throwable restricts direct user
implementation by design to keep the exception hierarchy clean and
predictable.

That said, I could be wrong about any of this, and in which case I would
genuinely appreciate you correcting my reasoning.

Regards,

Osama Aldemeery

On Mon, Mar 30, 2026 at 12:52 AM Anton Smirnov <[email protected]> wrote:

> Hi!
>
> On 30/03/2026 00:42, Osama Aldemeery wrote:
> > It follows the Stringable pattern: auto-implemented for any class
> > defining __invoke(), explicitly implementable with enforcement, and
> > covariant to callable in return type checks.
>
> Stringable is just a normal interface that can be used directly as any
> other regular interface, it's just also applied magically.
>
> Invokable cannot be a regular interface because the signature for
> __invoke is not fixed, so it's a "weird" interface with magic behavior
> like Throwable and Iterable. What is common about these weird interfaces
> is that they can't be directly implemented by user. I don't feel like
> breaking this rule is a good idea for something with no clear benefits.
>
> Second thing is that magic methods are not supposed to be used directly,
> so having __invoke is just an implementation detail, the consumer code
> should not check for that, that's a code smell.
>
> Anton
>

Reply via email to