Re: [PHP-DEV] [RFC] Namespace-scoped declares, again

  106567
August 13, 2019 17:05 rowan.collins@gmail.com (Rowan Collins)
On 13/08/2019 12:01, Mark Randall wrote:
> On 13/08/2019 10:02, Rowan Collins wrote: >> I really like this approach. It allows a package definition file to >> exist, without either the language or the header of each file having >> to define its location. > > # > # File: /lib/company/project1/a/b/MyClass.php > # > > >   declare_import(company[:label]); > >   namespace company/project1/a/b; > >   ... > > > # > # File: /lib/company/__nsmeta.php > # > > >   namespace company; > >   namespace_declare [:label] { >     strict_types=1; >     strict_operators=1; >     upgrade_errors_to_exceptions=E_ALL; >   } > >   final class __nsmeta { >     /* does nothing except be findable by the autoloader */ >     /* and defaults to private constructor so it can't be used */ >   }
This seems to be more complicated than Nicolas's version, and involve much more special magic, like the name __nsmeta, and the class that does nothing. I'm also not clear on how you're picturing the relationship between namespaces and packages. The way I understood the suggestion, you'd end up with something more like this, which feels much simpler and cleaner: # # File: /lib/company/project1/a/b/MyClass.php # 1,             'strict_operators' => 1,             'upgrade_errors_to_exceptions' => E_ALL         ];      } } Regards, -- Rowan Collins [IMSoP]
  106568
August 13, 2019 17:45 markyr@gmail.com (Mark Randall)
On 13/08/2019 18:05, Rowan Collins wrote:
> This seems to be more complicated than Nicolas's version, and involve > much more special magic, like the name __nsmeta, and the class that does > nothing. I'm also not clear on how you're picturing the relationship > between namespaces and packages.
I was looking for a way that would be intuitive to the existing system. We already have an existing userland system for locating a class. By using a placeholder class we can locate it using our existing logic.
> class project1 extends \PHP\Package { >     public function getParserDirectives() { >         return [ >             'strict_types' => 1, >             'strict_operators' => 1, >             'upgrade_errors_to_exceptions' => E_ALL >         ]; >      } > }
I thought about this as my first consideration, however it effectively requires that the PHP code within the package class is fully parsed and executed in order for it to retrieve the data. Consider pre-loading where the code is compiled, but not run, it would not be possible to use namespace level defines to add compile-level optimizations or checks (at least without some AST hackery). Meanwhile, the compiler itself could pull out a namespace_declare block and fully understand the information in it without actually needing to run anything. If I was writing a runtime package system, I would absolutely do it in the way you suggest, and in fact I already do for my own packages which deal with wrapping up css / js / html template files. Perfect for runtime, not so good for compile time, but if I'm wrong I dare say someone will let me know. Mark Randall
  106569
August 13, 2019 17:49 php-lists@koalephant.com (Stephen Reay)
> On 14 Aug 2019, at 00:05, Rowan Collins collins@gmail.com> wrote: > >> On 13/08/2019 12:01, Mark Randall wrote: >>> On 13/08/2019 10:02, Rowan Collins wrote: >>> I really like this approach. It allows a package definition file to exist, without either the language or the header of each file having to define its location. >> >> # >> # File: /lib/company/project1/a/b/MyClass.php >> # >> >> > >> declare_import(company[:label]); >> >> namespace company/project1/a/b; >> >> ... >> >> >> # >> # File: /lib/company/__nsmeta.php >> # >> >> > >> namespace company; >> >> namespace_declare [:label] { >> strict_types=1; >> strict_operators=1; >> upgrade_errors_to_exceptions=E_ALL; >> } >> >> final class __nsmeta { >> /* does nothing except be findable by the autoloader */ >> /* and defaults to private constructor so it can't be used */ >> } > > > This seems to be more complicated than Nicolas's version, and involve much more special magic, like the name __nsmeta, and the class that does nothing.. I'm also not clear on how you're picturing the relationship between namespaces and packages. > > The way I understood the suggestion, you'd end up with something more like this, which feels much simpler and cleaner: > > # > # File: /lib/company/project1/a/b/MyClass.php > # > > > declare(package=company/project1); > // or with a new keyword > package company/project1; > > namespace company/project1/a/b; > > ... > > > # > # File: /lib/company/project1.php > # > > > namespace company; > > class project1 extends \PHP\Package { > public function getParserDirectives() { > return [ > 'strict_types' => 1, > 'strict_operators' => 1, > 'upgrade_errors_to_exceptions' => E_ALL > ]; > } > } > > Regards, > > -- > Rowan Collins > [IMSoP] > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >
I think this approach is easier to follow (less magic) but has a (small) potential for conflict with existing code that may then require renaming or more (eg if a class existed with that proposed name, and is either a singleton and/or already extends another class). Is it feasible to instead require the class implements an interface that defines a static method? Building on that, could the concept of “do something to initialise this package” be made more generic: when a file declares it’s a member of a given package, the static method on the class that matches the package name is called, and it’s up to the developer what it does in that method. That would of course also then require a new function to set the declares with package scope to be useful for this particular problem, but it also allows more control and power for the concept of packages in general. Cheers Stephen