On Mon, Jul 1, 2024 at 9:02 AM Larry Garfield <la...@garfieldtech.com>
wrote:

> 2. Supporting multiple versions of the same class is *waaaay* out of
> scope.


No, it's actually the heart of the problem now that I've had a few days to
think on this, and it's something an autoloader can NOT resolve.


> You seem to imply Composer is the reason we cannot do that.  That's
> incorrect.  PHP has a single global symbol table for classes.  (And a
> separate one for functions for not-great historical reasons.)  Trying to
> define the same class twice will fatal the engine.  While there are some
> screwy conditional-include games you can play, they're fragile and still
> would not allow WP Plugin A to use v1 of a library and WP Plugin B to use
> v2 of a library.  I am not versed in that part of the engine, but I would
> be shocked if splitting up the global symbol table was possible, let alone
> feasible.
>
>
Let's assume all that's true.  Nothing you said stops this

import 'package v1' as \Package
import 'package v2' as \NewPackage

The problem with the current situation is the top level namespace of
packages are baked into the files. The import statement can alias the top
level namespace. Even if the engine cannot maintain multiple symbol tables,
what it can do is apply this aliasing on the fly as the same sort of hack
to the language that the current namespace implementation is (it's a blind
string replace, which is why they switched the namespace operator from ::
to the bloody escape character).

But for the alias to work the package has to tell import what its top level
namespace name is, especially for when the file is imported without an
alias, so that name will be used to graft the code in the package onto the
symbol table.

To illustrate, a package with a single file, its contents are

  class TestClass {}

Note, no namespace declared in the file itself.  The minimum contents of
the package declaration file, whatever form it takes, is:

  namespace TestPackage;

With just that in place there's no reason I can see for the engine to be
unable to do this.

import 'testpackage';

\TestPackage\TestClass // This is actually created symbol

import 'testpackage' as NewPackage

\NewPackage\TestClass  // This is the actually created symbol.

Set aside for a moment how the import statement resolves 'testpackage' -
the rules for resolving paths, urls, and version numbers are a different
topic.  But to say there is no way this can be done - bah.

What this does cut off at the knees though is allowing users who want this
flexibility to divest their control over what gets loaded for their code to
the discretion of an autoloader.  Much of the time, that's ok, but in more
complex applications it backfires. Sorta like typeless variables
themselves. For beginning programmers writing simple code they're fine.  I
know - I was one - and this simplicity hooked me in where I initially
couldn't get my head around datatyping with C# when I was young.  But at
the opposite end of the spectrum it backfires as having little to no
control over data types creates at least as many problems as it solves,
especially for automated testing.

We can have it both ways though. Let the infrastructure in place for
autoloading to stay in place, which will include the version of the code
called out in composer.json (assuming composer handles autoloading).  But
if I want to use a specific version of a package, even one that is in the
overall application I'm writing for such as WordPress or Drupal, I should
be able to do that. But that's going to require aliasing the package's name
as outlined above.

Reply via email to