On 05.07.2026 21:03, Larry Garfield wrote:
On Mon, Jun 29, 2026, at 5:32 PM, Michal Kral wrote:
Hi all,
Per Seifeddine's suggestion to keep this out of the karma-request
thread, I'm opening a pre-RFC discussion for scalar object methods --
calling a small, curated set of methods directly on scalar values, e.g.
$str->trim(), (3)->pow(2). There's a complete, tested implementation and
a full write-up (links below); I'd like to surface the strongest
objections before I write the formal RFC.
It may seem odd coming from me, but I am not in favor of scalar methods.
Specifically because of this line:
small, curated set of methods
That is bikeshed bait, and needlessly limiting. I would not support that.
What we should do instead is take a cue from Kotlin and C#: Extension
functions. Attach method-ish behavior to *any* type.
Sara Golemon and I worked up an idea of how it could work (with lots of "we could
spell it X, or Y, or Z" bits still in there) a while ago, though I've not done
anything with it since. (Plenty else to do.) The writeup is here:
https://gist.github.com/Crell/84cab7c3bf2b25e81b7f464945f6b678
I think that is a much better approach to take, and would be happy to work on
it if someone wants to partner on it. (Though it's definitely not getting into
8.6 at this point, obviously.)
--Larry Garfield
Hi Larry,
> small, curated set of methods
> That is bikeshed bait, and needlessly limiting.
Agreed, so let's not bikeshed it here. The set is deliberately minimal,
just enough to show the mechanism working; its contents and naming
should be their own separate RFC down the line. The part I want to
discuss is the mechanics: how dispatch on a scalar receiver should work.
The set is downstream of that.
> take a cue from Kotlin and C#: Extension functions. Attach method-ish
> behavior to any type.
I like it, and it's a real answer to the mechanics question, not just
the set one. Two honest things before I'd be sold:
- Scoping of the common ops. If I have to write `use Php\Str\length for
string;` in every file to call `$s->length()`, that's more ceremony than
the plain function it replaces. Do the core ops come always-in-scope,
with `use` reserved for userland extensions? The gist didn't pin that
down, and it seems load-bearing for whether this is pleasant to use day
to day.
- Which points at a hybrid I'd actually be keen on: core provides the
common scalar ops always-in-scope, extension functions handle
userland/domain-specific additions with `use`. That keeps your
extensibility and unbounded-ness without making the everyday case pay an
import.
Also, the compile-time pre-resolution your writeup mentions ("if we can
determine the type at compile time, pre-resolve, avoid runtime
overhead") is basically what I've already built for the guaranteed-type
cases, so there's working code for that half.
> would be happy to work on it if someone wants to partner on it
Genuinely interested. I'd like to see where this mechanics discussion
lands first, but I'm glad to talk — there's real overlap with what I
already have working, and no illusions about the 8.6 timeline.
Michal