On 01/06/2025 17:05, Larry Garfield wrote:
I think there's a key assumption here still that is at the root of much of the
disagreement in this thread.
Given that code from multiple files is clustered together into a "thing"
and Given we can use that "thing" to define a boundary for:
* name resolution (what Michael is after);
* visibility (what I am after);
* more efficient optimizations (what Arnaud showed is possible);
* various other things
Then the key question is: Who defines that boundary?
Is it the code*author* that defines that boundary? Or is it the code*consumer*?
Similarly, is it the code author or consumer that has to Do Work(tm) in order
to leverage the desired capability? Or both?
My take on this is that both need to exist as *separate* features.
The author should define the boundary for things like visibility and
optimisation. It should be possible to take an existing Composer
package, add some metadata to it in some way, and have the engine make
some useful assumptions. The consumer of that package should not need to
care about the difference, except in edge cases like trying to define
additional classes with the same prefix as a third-party package.
On the other hand, the consumer should define the boundary for isolating
name resolution. It should be possible to take any folder of PHP files,
with no metadata about package management, and load it in a context
where duplicate class names are allowed. The author of the package
shouldn't need to make any changes, except in edge cases like highly
dynamic code which needs additional hints to work correctly when sandboxed.
The first feature is an add-on to the extremely successful ecosystem
based on the assumption that packages will inter-operate based on agreed
names. The second feature is a bridge between that ecosystem and the
very different world of plugin-based web applications, which want to
manage multiple pieces of code which are not designed to co-operate, and
run them side by side.
JS has come up a few times as a comparison, because there the two
features overlap heavily. That's because the language has always started
from the opposite assumption to PHP: declarations in JS are local by
default, and can only be referenced outside of the current function
scope if explicitly passed outwards in some way. In PHP - and Java, C#,
and many others - the opposite is true, and declarations have a global
name by default; keywords like "private" and "internal" are then used to
indicate that although code can name something, it's not allowed to use it.
Both have their strengths and weaknesses, but at this point every JS
module going back 15+ years (CommonJS was founded in 2009, to
standardise existing practices) is based on the "interact by export"
model; and every PHP package going back 25+ years (PEAR founded in 1999;
Composer in 2011) is based on the "interact by name" model.
--
Rowan Tommins
[IMSoP]