[PATCH] allowing multiple namespaces per file plus namespaces with brackets

php.internals

Greg Beaver

19 years ago
Hi all, This patch is also available at http://pear.php.net/~greg/namespace.patch.txt The patch adds the syntax "namespace { *stuff }" and allows multiple namespaces per file with no performance penalty or added complexity as only 4 lines of code need to be changed, and 9 lines of code added to implement this support! Basically, there is one use case of multiple namespaces per file that the patch is designed to support, which is the ability to cram many files into a single file. I have done this for purposes of distributing things (prior to phar), it is used by some with phing tasks for performance reasons, and can have other uses as well. The patch provides the ability to do this, for example: <?php namespace One { require_once 'blah.php'; class MyClass extends blah { function test() { echo "OK\n"; } } function test() { echo "OK\n"; } } namespace Two { class MyClass { function test() { echo "OK\n"; } } function test() { echo "OK\n"; } } ?> Note that the old format "namespace OneRingToRuleThemAll;" is still fully supported, and should be the recommended format, as build tools can easily take an entire file, change namespace .*; into namespace .*{ and append <?php } ?> to the end of the file. The attached patch is against php6, but as you can see, a blind monkey could port it to PHP_5_3 when the time comes. All of the introduced changes are now tested, including the error message for nested namespace declarations, and the error message for multiple namespace declarations with ; (which was previously untested by .phpt tests) Thanks, Greg

David Coallier

19 years ago
Thanks. someone please commit that as fast as posible so no one can say anything ;-) On 8/20/07, Gregory Beaver <greg@chiaraquartet.net> wrote:
> Hi all, > > This patch is also available at > http://pear.php.net/~greg/namespace.patch.txt > > The patch adds the syntax "namespace { *stuff }" and allows multiple > namespaces per file with no performance penalty or added complexity as > only 4 lines of code need to be changed, and 9 lines of code added to > implement this support! > > Basically, there is one use case of multiple namespaces per file that > the patch is designed to support, which is the ability to cram many > files into a single file. I have done this for purposes of distributing > things (prior to phar), it is used by some with phing tasks for > performance reasons, and can have other uses as well. > > The patch provides the ability to do this, for example: > > <?php > namespace One { > require_once 'blah.php'; > class MyClass extends blah > { > function test() > { > echo "OK\n"; > } > } > function test() > { > echo "OK\n"; > } > } > > namespace Two { > class MyClass > { > function test() > { > echo "OK\n"; > } > } > function test() > { > echo "OK\n"; > } > } > ?> > > Note that the old format "namespace OneRingToRuleThemAll;" is still > fully supported, and should be the recommended format, as build tools > can easily take an entire file, change namespace .*; into namespace .*{ > and append <?php } ?> to the end of the file. > > The attached patch is against php6, but as you can see, a blind monkey > could port it to PHP_5_3 when the time comes. All of the introduced > changes are now tested, including the error message for nested namespace > declarations, and the error message for multiple namespace declarations > with ; (which was previously untested by .phpt tests) > > Thanks, > Greg >
-- David Coallier, Founder & Software Architect, Agora Production (http://agoraproduction.com) 51.42.06.70.18

Jani Taskinen

19 years ago
This is the wrong way to do things around here. If you want something in, just commit and ignore the noise on this list. --Jani david.coallier@nyphp.com kirjoitti:

Rasmus Lerdorf

19 years ago
Sheez, guys, slow down a tad. Just because he says "no performance penalty" in the description, doesn't make it true. Unless I missed something in the patch, I don't see how I would resolve the symbols at compile-time now which means it has been moved to the executor and in doing so it implies a huge performance penalty. -Rasmus Jani Taskinen wrote:

Greg Beaver

19 years ago
Rasmus Lerdorf wrote:
> Sheez, guys, slow down a tad. Just because he says "no performance > penalty" in the description, doesn't make it true. Unless I missed > something in the patch, I don't see how I would resolve the symbols at > compile-time now which means it has been moved to the executor and in > doing so it implies a huge performance penalty.
Hi Rasmus, I'm actually certain that the patch doesn't change any of the symbol resolution logic or add any need to move things from the compile-time to the executor. This is because the namespace implementation basically works more like a #define macro to auto-prepend class names and function names with namespace names. Old logic: request start => CG(namespace) = NULL T_NAMESPACE ...; zend_do_namespace() => defines CG(namespace) which is used for creating class and function entries php junk compile end => if (CG(namespace)) destruct CG(namespace), CG(namespace) = NULL New logic: request start => CG(namespace) = NULL [potential php junk] T_NAMESPACE ... { zend_do_namespace() => defines CG(namespace) which is used for creating class and function entries php junk } zend_do_end_namespace() => destruct CG(namespace), CG(namespace) = NULL php junk (which can include class/function entries, although that's a terrible idea) T_NAMESPACE ... { zend_do_namespace() => defines CG(namespace) which is used for creating class and function entries php junk } zend_do_end_namespace() => destruct CG(namespace), CG(namespace) = NULL compile end => if (CG(namespace)) destruct CG(namespace), CG(namespace) = NULL In other words, the only difference is that mid-parse the namespace #define-like prefix can be modified or removed. Greg

Andi Gutmans

19 years ago
Greg, Will review your patch... Thanks, Andi
> -----Original Message----- > From: Gregory Beaver [mailto:greg@chiaraquartet.net] > Sent: Monday, August 20, 2007 10:03 PM > To: Rasmus Lerdorf > Cc: internals Mailing List > Subject: Re: [PHP-DEV] [PATCH] allowing multiple namespaces per file > plus namespaces with brackets > > Rasmus Lerdorf wrote: > > Sheez, guys, slow down a tad. Just because he says "no performance > > penalty" in the description, doesn't make it true. Unless I missed > > something in the patch, I don't see how I would resolve the symbols > at > > compile-time now which means it has been moved to the executor and
in
> > doing so it implies a huge performance penalty. > > Hi Rasmus, > > I'm actually certain that the patch doesn't change any of the symbol > resolution logic or add any need to move things from the compile-time > to > the executor. This is because the namespace implementation basically > works more like a #define macro to auto-prepend class names and > function > names with namespace names. > > Old logic: > > request start => CG(namespace) = NULL > T_NAMESPACE ...; > zend_do_namespace() => defines CG(namespace) which is used for
creating
> class and function entries > php junk > compile end => if (CG(namespace)) destruct CG(namespace),
CG(namespace)
> = NULL > > New logic: > > request start => CG(namespace) = NULL > [potential php junk] > T_NAMESPACE ... { > zend_do_namespace() => defines CG(namespace) which is used for
creating
> class and function entries > php junk > } > zend_do_end_namespace() => destruct CG(namespace), CG(namespace) =
NULL
> php junk (which can include class/function entries, although that's a > terrible idea) > T_NAMESPACE ... { > zend_do_namespace() => defines CG(namespace) which is used for
creating
> class and function entries > php junk > } > zend_do_end_namespace() => destruct CG(namespace), CG(namespace) =
NULL
> compile end => if (CG(namespace)) destruct CG(namespace),
CG(namespace)

Rasmus Lerdorf

19 years ago
Gregory Beaver wrote:
> Rasmus Lerdorf wrote: >> Sheez, guys, slow down a tad. Just because he says "no performance >> penalty" in the description, doesn't make it true. Unless I missed >> something in the patch, I don't see how I would resolve the symbols at >> compile-time now which means it has been moved to the executor and in >> doing so it implies a huge performance penalty. > > Hi Rasmus, > > I'm actually certain that the patch doesn't change any of the symbol > resolution logic or add any need to move things from the compile-time to > the executor. This is because the namespace implementation basically > works more like a #define macro to auto-prepend class names and function > names with namespace names. > > Old logic: > > request start => CG(namespace) = NULL > T_NAMESPACE ...; > zend_do_namespace() => defines CG(namespace) which is used for creating > class and function entries > php junk > compile end => if (CG(namespace)) destruct CG(namespace), CG(namespace) > = NULL > > New logic: > > request start => CG(namespace) = NULL > [potential php junk] > T_NAMESPACE ... { > zend_do_namespace() => defines CG(namespace) which is used for creating > class and function entries > php junk > } > zend_do_end_namespace() => destruct CG(namespace), CG(namespace) = NULL > php junk (which can include class/function entries, although that's a > terrible idea) > T_NAMESPACE ... { > zend_do_namespace() => defines CG(namespace) which is used for creating > class and function entries > php junk > } > zend_do_end_namespace() => destruct CG(namespace), CG(namespace) = NULL > compile end => if (CG(namespace)) destruct CG(namespace), CG(namespace) > = NULL > > In other words, the only difference is that mid-parse the namespace > #define-like prefix can be modified or removed.
Right, which breaks the single-namespace per file rule. Opcode caches work on a per-file basis, so I know for a single op_array that I will never have to worry about a secondary namespace lookup because I know up front which namespace I am in. By allowing multiple namespaces per file I have to keep checking or do some other clever trick to figure it out. And nested namespaces really make a mess of this if something like this is allowed: foo.inc: namespace A { include 'bar.inc'; } bar.inc: namespace B { ... } In this case bar.inc's functions will either be A::B::func() or B::func() depending on how it is included which again means I can't do any compile-time optimization. -Rasmus

Andi Gutmans

19 years ago
Yep, we need to still review in detail but if it messes up the rules Rasmus has pointed out then it's a real issue. I think this is actually the reason why we didn't support it in our proposal. Andi
> -----Original Message----- > From: Rasmus Lerdorf [mailto:rasmus@lerdorf.com] > Sent: Monday, August 20, 2007 10:20 PM > To: Gregory Beaver > Cc: internals Mailing List > Subject: Re: [PHP-DEV] [PATCH] allowing multiple namespaces per file > plus namespaces with brackets > > Gregory Beaver wrote: > > Rasmus Lerdorf wrote: > >> Sheez, guys, slow down a tad. Just because he says "no performance > >> penalty" in the description, doesn't make it true. Unless I missed > >> something in the patch, I don't see how I would resolve the symbols > at > >> compile-time now which means it has been moved to the executor and > in > >> doing so it implies a huge performance penalty. > > > > Hi Rasmus, > > > > I'm actually certain that the patch doesn't change any of the symbol > > resolution logic or add any need to move things from the
compile-time
> to > > the executor. This is because the namespace implementation
basically
> > works more like a #define macro to auto-prepend class names and > function > > names with namespace names. > > > > Old logic: > > > > request start => CG(namespace) = NULL > > T_NAMESPACE ...; > > zend_do_namespace() => defines CG(namespace) which is used for > creating > > class and function entries > > php junk > > compile end => if (CG(namespace)) destruct CG(namespace), > CG(namespace) > > = NULL > > > > New logic: > > > > request start => CG(namespace) = NULL > > [potential php junk] > > T_NAMESPACE ... { > > zend_do_namespace() => defines CG(namespace) which is used for > creating > > class and function entries > > php junk > > } > > zend_do_end_namespace() => destruct CG(namespace), CG(namespace) = > NULL > > php junk (which can include class/function entries, although that's
a
> > terrible idea) > > T_NAMESPACE ... { > > zend_do_namespace() => defines CG(namespace) which is used for > creating > > class and function entries > > php junk > > } > > zend_do_end_namespace() => destruct CG(namespace), CG(namespace) = > NULL > > compile end => if (CG(namespace)) destruct CG(namespace), > CG(namespace) > > = NULL > > > > In other words, the only difference is that mid-parse the namespace > > #define-like prefix can be modified or removed. > > Right, which breaks the single-namespace per file rule. Opcode caches > work on a per-file basis, so I know for a single op_array that I will > never have to worry about a secondary namespace lookup because I know > up > front which namespace I am in. By allowing multiple namespaces per > file > I have to keep checking or do some other clever trick to figure it
out.
> > And nested namespaces really make a mess of this if something like
this

Greg Beaver

19 years ago
Rasmus Lerdorf wrote:
> Right, which breaks the single-namespace per file rule. Opcode caches > work on a per-file basis, so I know for a single op_array that I will > never have to worry about a secondary namespace lookup because I know up > front which namespace I am in. By allowing multiple namespaces per file > I have to keep checking or do some other clever trick to figure it out. > > And nested namespaces really make a mess of this if something like this > is allowed: > > foo.inc: > namespace A { > include 'bar.inc'; > } > > > bar.inc: > namespace B { > ... > } > > In this case bar.inc's functions will either be A::B::func() or > B::func() depending on how it is included which again means I can't do > any compile-time optimization.
Hi Rasmus, The patch explicitly disallows nested namespaces, the result of your sample above will be two separate namespaces, global and B. Also, the namespace processing is still per-file, it just adds a bit more complexity within a file for APC and company. I didn't realize you were talking about an opcode cache when speaking of moving things to the executor, but I still think by essentially implementing this as macro expansion, you can convert the two files to: foo.inc: include 'bar.inc'; bar.inc: class B::Whatever {...} and in other files, resolve imports in the same manner: another.inc: include 'bar.inc'; import B::Whatever; $a = new Whatever; becomes: another.inc: include 'bar.inc'; $a = new B::Whatever; What else is there here that I'm missing? I was under the impression that all of the namespacing tricks (as implemented) are determinate aliases to class names and function names that contain "::" in the actual CG() hash tables. I don't wish to cause trouble on these points, but I don't yet understand how the patch makes things any worse for APC, as all of the namespacing is still 100% deterministic and is a closed per-file system done at compile-time. Greg

Rasmus Lerdorf

19 years ago
Gregory Beaver wrote:
> Rasmus Lerdorf wrote: >> Right, which breaks the single-namespace per file rule. Opcode caches >> work on a per-file basis, so I know for a single op_array that I will >> never have to worry about a secondary namespace lookup because I know up >> front which namespace I am in. By allowing multiple namespaces per file >> I have to keep checking or do some other clever trick to figure it out. >> >> And nested namespaces really make a mess of this if something like this >> is allowed: >> >> foo.inc: >> namespace A { >> include 'bar.inc'; >> } >> >> >> bar.inc: >> namespace B { >> ... >> } >> >> In this case bar.inc's functions will either be A::B::func() or >> B::func() depending on how it is included which again means I can't do >> any compile-time optimization. > Hi Rasmus, > > The patch explicitly disallows nested namespaces, the result of your > sample above will be two separate namespaces, global and B. Also, the > namespace processing is still per-file, it just adds a bit more > complexity within a file for APC and company. I didn't realize you were > talking about an opcode cache when speaking of moving things to the > executor, but I still think by essentially implementing this as macro > expansion, you can convert the two files to:
Well, outside of an opcode cache, you wouldn't care whether the logic is in the compiler or the executor. But once you introduce an opcode cache, anything that you can resolve at compile-time means one less thing to do at execute time which means that the feature essentially becomes free once the file has been compiled and cached. Current opcode caches, including APC, will replace class and function definitions with NOPs in the cached op_arrays when it can definitively resolve them at compile-time. Things like autoload and conditional includes are examples of features that destroy this optimization because we need the runtime context in order to determine what to do which means we have to do it in the executor. Then of course there is the nightmare of class inheritance spanning includes and code that sometimes includes a file containing a child class conditionally and other times unconditionally. That caused us weeks, if not months, of headache in APC land.
> I don't wish to cause trouble on these points, but I don't yet > understand how the patch makes things any worse for APC, as all of the > namespacing is still 100% deterministic and is a closed per-file system > done at compile-time.
Perhaps it doesn't. What worries me is the ability to change the namespace mid-file. Maybe I can resolve this entirely at compile-time as long as no includes, imports or any other tricks can be used to break the namespace-to-one-file association. And we especially have to avoid anything that would cause a single file to change namespaces depending on how it is included and where it is included from. -Rasmus

Greg Beaver

19 years ago
Rasmus Lerdorf wrote:
> Well, outside of an opcode cache, you wouldn't care whether the logic is > in the compiler or the executor. But once you introduce an opcode > cache, anything that you can resolve at compile-time means one less > thing to do at execute time which means that the feature essentially > becomes free once the file has been compiled and cached. > > Current opcode caches, including APC, will replace class and function > definitions with NOPs in the cached op_arrays when it can definitively > resolve them at compile-time. Things like autoload and conditional > includes are examples of features that destroy this optimization because > we need the runtime context in order to determine what to do which means > we have to do it in the executor. Then of course there is the nightmare > of class inheritance spanning includes and code that sometimes includes > a file containing a child class conditionally and other times > unconditionally. That caused us weeks, if not months, of headache in > APC land. >
Hi, I remember this anguish, and have been following closely APC development through Gopal's blog, watching commit messages and so on, and have been proposing changes to PEAR2 (admittedly extremely controversial ones) that would make it more APC-friendly, so the last thing I want to do is add headaches in APC land, quite the opposite.
>> I don't wish to cause trouble on these points, but I don't yet >> understand how the patch makes things any worse for APC, as all of the >> namespacing is still 100% deterministic and is a closed per-file system >> done at compile-time. >> > > Perhaps it doesn't. What worries me is the ability to change the > namespace mid-file. Maybe I can resolve this entirely at compile-time > as long as no includes, imports or any other tricks can be used to break > the namespace-to-one-file association. And we especially have to avoid > anything that would cause a single file to change namespaces depending > on how it is included and where it is included from.
I understand this. I guess the way I would answer this is to question how you think APC would react differently to these two examples: example 1: file1.php: <?php namespace gronk; class bar {} ?> another.php: <?php namespace another; class boo {} ?> file2.php: <?php namespace foo; include 'file1.php'; include 'another.php'; import gronk::bar; class extender extends bar {} ?> ==== example 2: file1.php: <?php namespace gronk; class bar {} ?> file2.php: <?php include 'file1.php'; namespace another { class boo {} } import gronk::bar; namespace foo { class extender extends bar {} } ?> The two are functionally equivalent ways of doing things, the first without my patch, and the second with it. Would the second example's file2.php cause greater difficulty for APC in your estimation? Greg

Larry Garfield

19 years ago
Greg: You say that the old java-package-style definition still works, in addition to braces. I presume then that the following are equivalent: <?php namespace foo; class Bar { ... } ?> <?php namespace foo { class Bar { ... } } ?> What happens if you mix them? <?php namespace baz; namespace foo { class Bar { ... } } ?> Is the full name of the class then foo::Bar, baz::Bar, or foo::baz::Bar? Would the compiler have a heart attack if someone did: <?php namespace foo { namespace baz { class Bar { ... } } } ?> instead of: <?php namespace foo::baz; class Bar { ... } ?> or: namepsace foo::baz { class Bar { ... } } I don't know anywhere near enough about the engine code to be able to read your patch below, so I'm just trying to understand all the various implications of this syntax. On Monday 20 August 2007, Gregory Beaver wrote:
> Hi all, > > This patch is also available at > http://pear.php.net/~greg/namespace.patch.txt > > The patch adds the syntax "namespace { *stuff }" and allows multiple > namespaces per file with no performance penalty or added complexity as > only 4 lines of code need to be changed, and 9 lines of code added to > implement this support! > > Basically, there is one use case of multiple namespaces per file that > the patch is designed to support, which is the ability to cram many > files into a single file. I have done this for purposes of distributing > things (prior to phar), it is used by some with phing tasks for > performance reasons, and can have other uses as well. > > The patch provides the ability to do this, for example: > > <?php > namespace One { > require_once 'blah.php'; > class MyClass extends blah > { > function test() > { > echo "OK\n"; > } > } > function test() > { > echo "OK\n"; > } > } > > namespace Two { > class MyClass > { > function test() > { > echo "OK\n"; > } > } > function test() > { > echo "OK\n"; > } > } > ?> > > Note that the old format "namespace OneRingToRuleThemAll;" is still > fully supported, and should be the recommended format, as build tools > can easily take an entire file, change namespace .*; into namespace .*{ > and append <?php } ?> to the end of the file. > > The attached patch is against php6, but as you can see, a blind monkey > could port it to PHP_5_3 when the time comes. All of the introduced > changes are now tested, including the error message for nested namespace > declarations, and the error message for multiple namespace declarations > with ; (which was previously untested by .phpt tests) > > Thanks, > Greg
-- Larry Garfield AIM: LOLG42 larry@garfieldtech.com ICQ: 6817012 "If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it." -- Thomas Jefferson

Stanislav Malyshev

19 years ago
> What happens if you mix them? > > <?php > namespace baz; > > namespace foo { > class Bar { > ... > } > } > ?>
That's not the fun yet. This is: <?php namespace baz; namespace foo { ...whatever... } class bar {} ?> Now, is bar in namespace baz or not? I guess it is, otherwise it stops making any sense. So now when you see in the code it says "class bar" what do you do to know which namespace it is? Right, you go up to the code, counting closing and open brackets and hoping you didn't miss any and try to figure out if it's that main namespace or one of the other ones. Now next question - how ones in namespace foo are supposed to call class bar? They'd have to call it by full name, baz::bar, right? Welcome back, long names. But wait, we could use an import, right? So now we'd have block-local imports. And we'd have to track them per namespace-block. BTW, what about imports in baz - are they active in foo? What if baz wants to talk to class in foo - should it import it? And BTW - how the patch solves it - I didn't read all of it, but not sure it does it correctly.
> Would the compiler have a heart attack if someone did: > > <?php > namespace foo { > namespace baz { > class Bar { ... } > } > } > ?>
This syntax implies that baz has access to names in foo. The separate syntax doesn't. But that's only part of the story - remember the names/imports story above? Now take that and make it unlimited depth stack, since you'd have to track everything on *each* nesting level separately. I wouldn't want to open this can of worms. That'd produce messy engine and messy code.
-- Stanislav Malyshev, Zend Software Architect stas@zend.com http://www.zend.com/ (408)253-8829 MSN: stas@zend.com

Greg Beaver

19 years ago
Stanislav Malyshev wrote:
>> What happens if you mix them? >> <?php namespace baz; >> >> namespace foo { >> class Bar { >> ... >> } >> } >> ?> > > That's not the fun yet. This is: > > <?php > namespace baz; > > namespace foo { ...whatever... } > > class bar {} > > ?>
If by fun you mean "Fatal error: Namespace cannot be declared twice (without brackets) or nested within brackets in ..." To clarify, the patch works as follows: when namespace baz; is encountered, CG(current_namespace) is set to a non-NULL zstr (name->u.constant). Later on, when you try to namespace foo {}, this check fails: if (CG(current_namespace)) { zend_error(E_COMPILE_ERROR, "Namespace cannot be declared twice (without brackets) or nested within brackets"); } In other words, if there is a current namespace present, you can't declare another or redeclare. This code also fails with the same E_COMPILE_ERROR above (and is one of the new tests in the patch): <?php namespace baz; namespace foo; class bar {} ?>
> Now, is bar in namespace baz or not? I guess it is, otherwise it stops > making any sense. So now when you see in the code it says "class bar" > what do you do to know which namespace it is? Right, you go up to the > code, counting closing and open brackets and hoping you didn't miss any > and try to figure out if it's that main namespace or one of the other > ones. Now next question - how ones in namespace foo are supposed to call > class bar? They'd have to call it by full name, baz::bar, right? Welcome > back, long names. But wait, we could use an import, right? So now we'd > have block-local imports. And we'd have to track them per > namespace-block. BTW, what about imports in baz - are they active in > foo? What if baz wants to talk to class in foo - should it import it? > And BTW - how the patch solves it - I didn't read all of it, but not > sure it does it correctly. > >> Would the compiler have a heart attack if someone did: >> >> <?php >> namespace foo { >> namespace baz { >> class Bar { ... } >> } >> } >> ?> > > This syntax implies that baz has access to names in foo. The separate > syntax doesn't. But that's only part of the story - remember the > names/imports story above? Now take that and make it unlimited depth > stack, since you'd have to track everything on *each* nesting level > separately. I wouldn't want to open this can of worms. That'd produce > messy engine and messy code.
I don't want to open this can of worms either, and so I didn't. :) Greg

David Zülke

19 years ago
I think there should be just one way to designate a namespace, not two different ones with different behaviors. David Am 21.08.2007 um 21:09 schrieb Gregory Beaver:

Greg Beaver

19 years ago
David Zülke wrote:
> I think there should be just one way to designate a namespace, not two > different ones with different behaviors.
Hi David, First, the behaviors are not different, just the syntax. Of course you can have more than one namespace per file with brackets, but the stuff within that namespace reacts identically to the other format. Second, if the consensus is one syntax, I'd say that's not really a big deal. Doing so would simply involve removing one line from zend_language_parser.y, rewording the error message, and dropping the brackets parameters from zend_do_namespace's proto. For now, it's better to investigate the ramifications of the patch first, as this decision could be made quite easily closer to the first release. Greg

David Zülke

19 years ago
Greg, sorry, "behavior" was probably not the right word. In any case, they are different, because the one approach allows users to declare just one namespace, and the other one allows to declare any number of namespaces. That's what I meant. There really is no need for ambiguities like this; the curly braces syntax would be enough. David Am 21.08.2007 um 22:05 schrieb Gregory Beaver:

Stanislav Malyshev

19 years ago
>> <?php >> namespace baz; >> >> namespace foo { ...whatever... } >> >> class bar {} >> >> ?> > > If by fun you mean "Fatal error: Namespace cannot be declared twice > (without brackets) or nested within brackets in ..."
Ah, I didn't read it good enough - was under impression mixing them was allowed.
-- Stanislav Malyshev, Zend Software Architect stas@zend.com http://www.zend.com/ (408)253-8829 MSN: stas@zend.com

Greg Beaver

19 years ago
Larry Garfield wrote:
> Greg: You say that the old java-package-style definition still works, in > addition to braces. I presume then that the following are equivalent: > > <?php > namespace foo; > > class Bar { > ... > } > ?> > > <?php > namespace foo { > class Bar { > ... > } > } > ?> > > What happens if you mix them? > > <?php > namespace baz; > > namespace foo { > class Bar { > ... > } > } > ?>
compiler error - if you use namespace OneToRuleThemAll; then you can't additionally use namespace another {}
> Would the compiler have a heart attack if someone did: > > <?php > namespace foo { > namespace baz { > class Bar { ... } > } > } > ?>
compiler error Greg

Dmitry Stogov

19 years ago
How about "import" statements? The had effect on current file. How they will behave with your patch? The import in one namespace will affect following namespaces... :) Also this change is inconsistent with renaming "namespace" to "package". Thanks. Dmitry.

Marcus Börger

19 years ago
Hello Dmitry, LOL!!!!! climbing up the chair again, this is the most stupiest arguemnt ever. didn't you just yesterday suggest we keep it namespace anyway until we are done. And didn't you guys say that we might end up with something that really is namespaces anyway. Please guyse read your own arguments if you do not manage to remember them. marcus Tuesday, August 21, 2007, 10:16:39 AM, you wrote:
> How about "import" statements? > The had effect on current file. How they will behave with your patch? > The import in one namespace will affect following namespaces... :)
> Also this change is inconsistent with renaming "namespace" to "package".
> Thanks. Dmitry.
>> -----Original Message----- >> From: Gregory Beaver [mailto:greg@chiaraquartet.net] >> Sent: Monday, August 20, 2007 11:57 PM >> To: internals Mailing List; Dmitry Stogov; Stanislav Malyshev >> Subject: [PHP-DEV] [PATCH] allowing multiple namespaces per >> file plus namespaces with brackets >> >> >> Hi all, >> >> This patch is also available at >> http://pear.php.net/~greg/namespace.patch.txt >> >> The patch adds the syntax "namespace { *stuff }" and allows >> multiple namespaces per file with no performance penalty or >> added complexity as only 4 lines of code need to be changed, >> and 9 lines of code added to implement this support! >> >> Basically, there is one use case of multiple namespaces per >> file that the patch is designed to support, which is the >> ability to cram many files into a single file. I have done >> this for purposes of distributing things (prior to phar), it >> is used by some with phing tasks for performance reasons, and >> can have other uses as well. >> >> The patch provides the ability to do this, for example: >> >> <?php >> namespace One { >> require_once 'blah.php'; >> class MyClass extends blah >> { >> function test() >> { >> echo "OK\n"; >> } >> } >> function test() >> { >> echo "OK\n"; >> } >> } >> >> namespace Two { >> class MyClass >> { >> function test() >> { >> echo "OK\n"; >> } >> } >> function test() >> { >> echo "OK\n"; >> } >> } >> ?> >> >> Note that the old format "namespace OneRingToRuleThemAll;" is >> still fully supported, and should be the recommended format, >> as build tools can easily take an entire file, change >> namespace .*; into namespace .*{ and append <?php } ?> to the >> end of the file. >> >> The attached patch is against php6, but as you can see, a >> blind monkey could port it to PHP_5_3 when the time comes. >> All of the introduced changes are now tested, including the >> error message for nested namespace declarations, and the >> error message for multiple namespace declarations with ; >> (which was previously untested by .phpt tests) >> >> Thanks, >> Greg >>
Best regards, Marcus

Dmitry Stogov

19 years ago
Marcus, You can laugh as you like. I never said that I didn't like rename "namespace" to "package". I asked to wait with decision because the whole concept is not finalized yet. For example "packages" and "multiple namespaces in single file" are inconsistent. Anyway, I prefer developing PHP than argue with your unconstructive emails. Thanks. Dmitry.

Marcus Börger

19 years ago
Hello Dmitry, so please stick to your own arguments and don't chnage them at random. And spare us with stupid arguemnts. The renaming patch was perfectly valid when offered and I am sure the author of that patch would fix it before comitting if allowed to. So saying that the patch is wrong just because normal development continued is very offending behavior and does not bring us anywhere. And sorry but in cases like this I will stick to pointing them out. Whether anyone likes it or not. marcus Tuesday, August 21, 2007, 3:28:11 PM, you wrote:
> Marcus,
> You can laugh as you like.
> I never said that I didn't like rename "namespace" to "package". > I asked to wait with decision because the whole concept is not finalized > yet. > For example "packages" and "multiple namespaces in single file" are > inconsistent.
> Anyway, I prefer developing PHP than argue with your unconstructive emails.
> Thanks. Dmitry.
>> -----Original Message----- >> From: Marcus Boerger [mailto:helly@php.net] >> Sent: Tuesday, August 21, 2007 2:24 PM >> To: Dmitry Stogov >> Cc: 'Gregory Beaver'; 'internals Mailing List'; 'Stanislav Malyshev' >> Subject: Re: [PHP-DEV] [PATCH] allowing multiple namespaces >> per file plus namespaces with brackets >> >> >> Hello Dmitry, >> >> LOL!!!!! >> >> climbing up the chair again, this is the most stupiest arguemnt ever. >> >> didn't you just yesterday suggest we keep it namespace anyway >> until we are done. And didn't you guys say that we might end >> up with something that really is namespaces anyway. >> >> Please guyse read your own arguments if you do not manage to >> remember them. >> >> marcus >> >> Tuesday, August 21, 2007, 10:16:39 AM, you wrote: >> >> > How about "import" statements? >> > The had effect on current file. How they will behave with >> your patch? >> > The import in one namespace will affect following namespaces... :) >> >> > Also this change is inconsistent with renaming "namespace" to >> > "package". >> >> > Thanks. Dmitry. >> >> >> >> -----Original Message----- >> >> From: Gregory Beaver [mailto:greg@chiaraquartet.net] >> >> Sent: Monday, August 20, 2007 11:57 PM >> >> To: internals Mailing List; Dmitry Stogov; Stanislav Malyshev >> >> Subject: [PHP-DEV] [PATCH] allowing multiple namespaces per >> >> file plus namespaces with brackets >> >> >> >> >> >> Hi all, >> >> >> >> This patch is also available at >> >> http://pear.php.net/~greg/namespace.patch.txt >> >> >> >> The patch adds the syntax "namespace { *stuff }" and allows >> >> multiple namespaces per file with no performance penalty or >> >> added complexity as only 4 lines of code need to be changed, >> >> and 9 lines of code added to implement this support! >> >> >> >> Basically, there is one use case of multiple namespaces per >> >> file that the patch is designed to support, which is the >> >> ability to cram many files into a single file. I have done >> >> this for purposes of distributing things (prior to phar), it >> >> is used by some with phing tasks for performance reasons, and >> >> can have other uses as well. >> >> >> >> The patch provides the ability to do this, for example: >> >> >> >> <?php >> >> namespace One { >> >> require_once 'blah.php'; >> >> class MyClass extends blah >> >> { >> >> function test() >> >> { >> >> echo "OK\n"; >> >> } >> >> } >> >> function test() >> >> { >> >> echo "OK\n"; >> >> } >> >> } >> >> >> >> namespace Two { >> >> class MyClass >> >> { >> >> function test() >> >> { >> >> echo "OK\n"; >> >> } >> >> } >> >> function test() >> >> { >> >> echo "OK\n"; >> >> } >> >> } >> >> ?> >> >> >> >> Note that the old format "namespace OneRingToRuleThemAll;" is >> >> still fully supported, and should be the recommended format, >> >> as build tools can easily take an entire file, change >> >> namespace .*; into namespace .*{ and append <?php } ?> to the >> >> end of the file. >> >> >> >> The attached patch is against php6, but as you can see, a >> >> blind monkey could port it to PHP_5_3 when the time comes. >> >> All of the introduced changes are now tested, including the >> >> error message for nested namespace declarations, and the >> >> error message for multiple namespace declarations with ; >> >> (which was previously untested by .phpt tests) >> >> >> >> Thanks, >> >> Greg >> >> >> >> >> >> >> Best regards, >> Marcus >>
Best regards, Marcus

Stanislav Malyshev

19 years ago
> Hello Dmitry, > > LOL!!!!! > > climbing up the chair again, this is the most stupiest argument ever.
Could you please keep the attitude down? Calling names is not going to help anything.
> didn't you just yesterday suggest we keep it namespace anyway until we > are done. And didn't you guys say that we might end up with something that > really is namespaces anyway. > > Please guyse read your own arguments if you do not manage to remember them.
We discuss and consider a lot of options. Including ones that contradict. That's the meaning of discussion - to consider all options and find out the best. Dmitry was absolutely right to note that naming can wait until we finalize all the concept, and that braces support namespace naming. Though, they create many other problems, which we need to have addressed before we could consider adding it to the concept.
-- Stanislav Malyshev, Zend Software Architect stas@zend.com http://www.zend.com/ (408)253-8829 MSN: stas@zend.com

Guilherme Blanco

19 years ago
Hi, I'll try to answer some of the questions I saw here based on Gregory's patch and I will ask for more information about external things that I probably misunderstood. > And nested namespaces really make a mess of this if something like this > is allowed: > > foo.inc: > namespace A { > include 'bar.inc'; > } > > > bar.inc: > namespace B { > ... > } This is not currently allowed. There are still a limitation of nested namespaces. > <?php > namespace baz; > > namespace foo { > class Bar { > ... > } > } > ?> It's the same as the previous situation. You have a current namespace scope, so it'll raise an error. > Would the compiler have a heart attack if someone did: > > <?php > namespace foo { > namespace baz { > class Bar { ... } > } > } > ?> It'll only throw this error: "Namespace cannot be defined twice (without brackets) or nested within brackets" > <?php > namespace baz; > > namespace foo { ...whatever... } > > class bar {} > > ?> > > Now, is bar in namespace baz or not? No, there is a syntax error. And you'll receive the same message I showed before. > Also this change is inconsistent with renaming "namespace" to "package". Exactly. I am interested to see namespace support in PHP too, but the current implementation tell me the contrary. Gregory purposed a patch to remove one of the PHP namespace limitation. =) AFAIK, this patch do not have performance impact. It only tries to add another way to define namespaces. So it's like the original implementation, but it holds the current_namespace based in the current scope (old behavior was the entire file, not it's either the entire file OR the namespace block (both are disallowed)). I don't understand very well what Rasmus tried to mention with nested namespaces and opcache, but seems there're a limitation and I am interested to know which (if possible, try to explain in other words)... =) Why am I asking this? I am changing the Gregory's patch... now, current_namespace holds a zval. I am changing it first to a stack, and pushing and popping the namespaces based on block declaration. So, the piece of code Stanislav pointed before: namespace Foo; namespace Bar { class Test {} } class Test {} Is being resolved as Foo::Bar::Test and Foo::Test. BUT... it's not working as expected yet. Currently it's defining as: Foo::Test and Bar::Test. This is my first try to do something internally in PHP, so I'm having huge headaches to modify the source. My first try to avoid this: namespace Long::Nspace::Declaration::In:The::TopOf::TheFile; class Foo {} To something more clean and organized, like: namespace Logn { namespace Nspace { ... } } I know there're a lot of other impacts by doing this, but since this is a draft yet, it can be implemented more and more functionalities, like Inner Namespace able to use parent definitions. But this is just a beginning. Also, mentioning the Rasmus piece of code: foo.inc: namespace A { include 'bar.inc'; } bar.inc: namespace B { ... } I don't know how do you control it internally, but as long as this is the only call in the entire script, the right scope should be: A::B, and not B. If I include bar.inc outside any namespace scope, then it should be B. Waiting a response... Best regards, On 8/21/07, Stanislav Malyshev <stas@zend.com> wrote: > > Hello Dmitry, > > > > LOL!!!!! > > > > climbing up the chair again, this is the most stupiest argument ever. > > Could you please keep the attitude down? Calling names is not going to > help anything. > > > didn't you just yesterday suggest we keep it namespace anyway until we > > are done. And didn't you guys say that we might end up with something that > > really is namespaces anyway. > > > > Please guyse read your own arguments if you do not manage to remember them. > > We discuss and consider a lot of options. Including ones that > contradict. That's the meaning of discussion - to consider all options > and find out the best. Dmitry was absolutely right to note that naming > can wait until we finalize all the concept, and that braces support > namespace naming. Though, they create many other problems, which we need > to have addressed before we could consider adding it to the concept. > -- > Stanislav Malyshev, Zend Software Architect > stas@zend.com http://www.zend.com/ > (408)253-8829 MSN: stas@zend.com > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > -- Guilherme Blanco - Web Developer CBC - Certified Bindows Consultant Cell Phone: +55 (16) 9166-6902 MSN: guilhermeblanco@hotmail.com URL: http://blog.bisna.com São Carlos - SP/Brazil

Larry Garfield

19 years ago
On Tuesday 21 August 2007, Guilherme Blanco wrote:
> Also, mentioning the Rasmus piece of code: > > foo.inc: > namespace A { > include 'bar.inc'; > } > > > bar.inc: > namespace B { > ... > } > > I don't know how do you control it internally, but as long as this is > the only call in the entire script, the right scope should be: A::B, > and not B. If I include bar.inc outside any namespace scope, then it > should be B.
I have to disagree here. If I'm doing conditional includes (I know opcode caches don't like it, but any modular, plugin-based system rather has to), then I don't want to have the namespace of my included code vary depending on where I include it. That means that I need to force all of my include statements to be outside of a namespace unless I want namespaces to stack, and stack differently depending on where they get called. That's a huge can of worms I really don't want to deal with. Were the code above to be run, I'd expect and want a namespace A and a namespace B, and that's it. My code ends up being too non-deterministic otherwise. Forget the compiler, I can't cope with that. :-)
-- Larry Garfield AIM: LOLG42 larry@garfieldtech.com ICQ: 6817012 "If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it." -- Thomas Jefferson

Rasmus Lerdorf

19 years ago
Guilherme Blanco wrote:
> I don't understand very well what Rasmus tried to mention with nested > namespaces and opcache, but seems there're a limitation and I am > interested to know which (if possible, try to explain in other > words)... =) > Why am I asking this? I am changing the Gregory's patch... now, > current_namespace holds a zval. I am changing it first to a stack, and > pushing and popping the namespaces based on block declaration.
The reason Dmitry went with a package-like one-namespace per file approach was to avoid any confusion that might be caused by braces and a stack-like expectation. For example, when you have code like this: function foo() { include 'bar.inc'; } Then everything in bar.inc becomes part of the foo() function. So, in a stack-based namespace implementation with braces you might have code like this: namespace foo { include 'bar.inc'; } Now, if bar.inc defines functions or classes, one would logically expect these to be in the foo namespace. But this is exactly what we want to avoid. Imagine this code: include 'bar.inc'; namespace foo { include 'bar.inc'; } This is where everything starts getting complicated for an opcode cache because it would really like to resolve everything at compile-time. But in this case the functions and classes in bar.inc have different names depending on the context of the include. Opcode caches already have to deal with this to some extent in terms of conditional includes, but this would take it a step further, and the last thing we need is to make the opcode caches more complex and slow down the engine further by making every symbol more complex to resolve. I honestly don't have much use for namespaces and I couldn't care less what they are called, but I do care that they don't slow down code that doesn't use them, and even for code that does use them, I would hate to have another autoload-like performance penalty for what would otherwise be a useful feature in some cases. -Rasmus

Marcus Börger

19 years ago
Hello Rasmus, the limitations given here and very good explained should imo stay. They should because that is not only easier to understand and easier for anything that has to deal with it like opcode caches and whatnot but also adhrers to the good old KISS approach of PHP. That said, instead of changing the current implementation every day we should step back a bit and first find a consensus whether we want anything more or even anything less than what we currently have. My personal feeling is that we should stick to one name binding per file. And we should do so without braces (if I want it complex I just take a more complex language). marcus Wednesday, August 22, 2007, 7:46:47 AM, you wrote:
> Guilherme Blanco wrote: >> I don't understand very well what Rasmus tried to mention with nested >> namespaces and opcache, but seems there're a limitation and I am >> interested to know which (if possible, try to explain in other >> words)... >> Why am I asking this? I am changing the Gregory's patch... now, >> current_namespace holds a zval. I am changing it first to a stack, and >> pushing and popping the namespaces based on block declaration.
> The reason Dmitry went with a package-like one-namespace per file > approach was to avoid any confusion that might be caused by braces and a > stack-like expectation. For example, when you have code like this:
> function foo() { > include 'bar.inc'; > }
> Then everything in bar.inc becomes part of the foo() function. So, in a > stack-based namespace implementation with braces you might have code > like this:
> namespace foo { > include 'bar.inc'; > }
> Now, if bar.inc defines functions or classes, one would logically expect > these to be in the foo namespace. But this is exactly what we want to > avoid. Imagine this code:
> include 'bar.inc'; > namespace foo { > include 'bar.inc'; > }
> This is where everything starts getting complicated for an opcode cache > because it would really like to resolve everything at compile-time. But > in this case the functions and classes in bar.inc have different names > depending on the context of the include. Opcode caches already have to > deal with this to some extent in terms of conditional includes, but this > would take it a step further, and the last thing we need is to make the > opcode caches more complex and slow down the engine further by making > every symbol more complex to resolve.
> I honestly don't have much use for namespaces and I couldn't care less > what they are called, but I do care that they don't slow down code that > doesn't use them, and even for code that does use them, I would hate to > have another autoload-like performance penalty for what would otherwise > be a useful feature in some cases.
> -Rasmus
Best regards, Marcus

Robert Cummings

19 years ago
On Wed, 2007-08-22 at 13:57 +0200, Marcus Boerger wrote:
> Hello Rasmus, > > the limitations given here and very good explained should imo stay. They > should because that is not only easier to understand and easier for anything > that has to deal with it like opcode caches and whatnot but also adhrers to > the good old KISS approach of PHP. > > That said, instead of changing the current implementation every day we > should step back a bit and first find a consensus whether we want anything > more or even anything less than what we currently have. > > My personal feeling is that we should stick to one name binding per file. > And we should do so without braces (if I want it complex I just take a more > complex language).
While I agree with the one namespace per file camp I think your above argument "if I want it complex I just take a more complex language" is akin to saying "If I want it OOP I'll take a more OOP language". I'm sure you'll agree that's not a very good argument. Cheers, Rob.
-- ........................................................... SwarmBuy.com - http://www.swarmbuy.com Leveraging the buying power of the masses! ...........................................................

Lukas Kahwe Smith

19 years ago
Robert Cummings wrote:
> On Wed, 2007-08-22 at 13:57 +0200, Marcus Boerger wrote: >> Hello Rasmus, >> >> the limitations given here and very good explained should imo stay. They >> should because that is not only easier to understand and easier for anything >> that has to deal with it like opcode caches and whatnot but also adhrers to >> the good old KISS approach of PHP. >> >> That said, instead of changing the current implementation every day we >> should step back a bit and first find a consensus whether we want anything >> more or even anything less than what we currently have. >> >> My personal feeling is that we should stick to one name binding per file. >> And we should do so without braces (if I want it complex I just take a more >> complex language). > > While I agree with the one namespace per file camp I think your above > argument "if I want it complex I just take a more complex language" is > akin to saying "If I want it OOP I'll take a more OOP language". I'm > sure you'll agree that's not a very good argument.
Make as much hard but common stuff easy, keep the easy stuff easy and make the hard stuff possible. Could this be our mantra? regards, Lukas

Robert Cummings

19 years ago
On Wed, 2007-08-22 at 16:15 +0200, Lukas Kahwe Smith wrote:
> Robert Cummings wrote: > > On Wed, 2007-08-22 at 13:57 +0200, Marcus Boerger wrote: > >> Hello Rasmus, > >> > >> the limitations given here and very good explained should imo stay. They > >> should because that is not only easier to understand and easier for anything > >> that has to deal with it like opcode caches and whatnot but also adhrers to > >> the good old KISS approach of PHP. > >> > >> That said, instead of changing the current implementation every day we > >> should step back a bit and first find a consensus whether we want anything > >> more or even anything less than what we currently have. > >> > >> My personal feeling is that we should stick to one name binding per file. > >> And we should do so without braces (if I want it complex I just take a more > >> complex language). > > > > While I agree with the one namespace per file camp I think your above > > argument "if I want it complex I just take a more complex language" is > > akin to saying "If I want it OOP I'll take a more OOP language". I'm > > sure you'll agree that's not a very good argument. > > Make as much hard but common stuff easy, keep the easy stuff easy and > make the hard stuff possible. Could this be our mantra?
It's a great mantra, just not always possible :) Cheers, Rob.
-- ........................................................... SwarmBuy.com - http://www.swarmbuy.com Leveraging the buying power of the masses! ...........................................................

Greg Beaver

19 years ago
Dmitry Stogov wrote:
> How about "import" statements? > The had effect on current file. How they will behave with your patch? > The import in one namespace will affect following namespaces... :)
That's correct, import remains a per-file operation, and I pray to god that no one suggests making it anything else. This does mean, however, that if you try to "combine" two files that contain import statements, it will be necessary to expand the imports. Fortunately, since namespaces and imports are absolutely deterministic, this can be done quite easily. Note that your concern above is simply a documentation issue, users will use import correctly if the manual begins with something like: ====== import allows aliasing specific namespaced files and classes within a file. For example: <?php // externalfile.php defines namespace foo and class bar require 'externalfile.php'; import foo::bar $a = new bar; ?> Note that once a name has been imported to a file, all new classes within the file cannot conflict. The following file generates a fatal error even though gronk::bar is : <?php namespace foo { class bar {} } import foo::bar; namespace gronk { class bar {} } ?> Fatal error: Class name 'bar' coflicts with import name ===== That will clear up any possible confusion.
> Also this change is inconsistent with renaming "namespace" to "package".
Well it kind of makes namespaces behave more like namespaces, don't you think? I already expressed an earlier opinion that namespaces should be called namespaces, because that is a better name, but that is irrelevant. This patch has nothing to do with what we call the things, it adds missing functionality. You could say that it allows more than one package per file, but then you end up with namespaces in my opinion, so there you go. :) Greg

Stanislav Malyshev

19 years ago
> that if you try to "combine" two files that contain import statements, > it will be necessary to expand the imports. Fortunately, since
What do you mean by "expand"?
> import allows aliasing specific namespaced files and classes within a > file. For example:
But import has nothing to do with files. import works on names, not files.
> <?php > namespace foo { > class bar {} > } > import foo::bar; > namespace gronk { > class bar {} > } > ?> > > Fatal error: Class name 'bar' coflicts with import name
Ouch! So I can't actually combine namespaces from different areas - how I'm supposed to know when I write "gronk" that somebody is going to stick this code into the context that already has the name "bar" in it? It's exactly the problem namespaces are meant to solve! Moreover, if you take two files with working code and copy-paste them into one file, they have a lot of chance of stopping working. If this isn't confusion, I don't know what is.
> That will clear up any possible confusion.
No, on the contrary - it would create a lot of confusion, since now you can break namespaced code with code outside namespace, which wasn't supposed to happen by definition.
> Well it kind of makes namespaces behave more like namespaces, don't you
Please stop this "only C++ implementation is right" thing.
-- Stanislav Malyshev, Zend Software Architect stas@zend.com http://www.zend.com/ (408)253-8829 MSN: stas@zend.com

Greg Beaver

19 years ago
Stanislav Malyshev wrote:
>> that if you try to "combine" two files that contain import statements, >> it will be necessary to expand the imports. Fortunately, since > > What do you mean by "expand"? > >> import allows aliasing specific namespaced files and classes within a >> file. For example: > > But import has nothing to do with files. import works on names, not files.
s/files/functions/ I mis-typed and didn't notice, sorry.
>> <?php >> namespace foo { >> class bar {} >> } >> import foo::bar; >> namespace gronk { >> class bar {} >> } >> ?> >> >> Fatal error: Class name 'bar' coflicts with import name > > Ouch! So I can't actually combine namespaces from different areas - > how I'm supposed to know when I write "gronk" that somebody is going > to stick this code into the context that already has the name "bar" in > it? It's exactly the problem namespaces are meant to solve! Moreover, > if you take two files with working code and copy-paste them into one > file, they have a lot of chance of stopping working. If this isn't > confusion, I don't know what is.
Careful Stas :), you probably missed the "import foo::bar;" This code works just fine: <?php namespace foo { class bar {} } namespace gronk { class bar {} } ?> No fatal errors, everybody is happy. The problem is importing the "bar" identifier. This code also fails with the same fatal error for the same reason: file1.php: <?php namespace foo; class bar {} ?> file2.php: <?php namespace gronk; import foo::bar; class bar {} ?>
>> That will clear up any possible confusion. > > No, on the contrary - it would create a lot of confusion, since now > you can break namespaced code with code outside namespace, which > wasn't supposed to happen by definition.
It still doesn't. As I pointed out above, the same error is possible with the current implementation pre-my patch.
>> Well it kind of makes namespaces behave more like namespaces, don't you > > Please stop this "only C++ implementation is right" thing.
I don't care about C++. I'm only talking about the patch I proposed. Thanks, Greg

Stanislav Malyshev

19 years ago
> Careful Stas :), you probably missed the "import foo::bar;" This code > works just fine:
No I didn't. That's the whole point - once you do import outside namespace, you can break stuff inside. Namespace is supposed to be isolated from other namespaces, that's the whole point of it. But if you make import have effects on other namespaces, then code in one namespace can break other.
> file1.php: > <?php > namespace foo; > class bar {} > ?> > > file2.php: > <?php > namespace gronk; > import foo::bar; > class bar {} > ?>
The problem is not this code. The problem is this code: file1.php <?php namespace foo; import otherfoo::bar; ?> file2.php: <?php namespace gronk; class bar {} ?> Would start failing too once you merge them in one file, even though they worked just fine before.
-- Stanislav Malyshev, Zend Software Architect stas@zend.com http://www.zend.com/ (408)253-8829 MSN: stas@zend.com

Greg Beaver

19 years ago
Stanislav Malyshev wrote:
>> file1.php: >> <?php >> namespace foo; >> class bar {} >> ?> >> >> file2.php: >> <?php >> namespace gronk; >> import foo::bar; >> class bar {} >> ?> > > The problem is not this code. The problem is this code: > > file1.php > <?php > namespace foo; > import otherfoo::bar; > ?> > > file2.php: > <?php > namespace gronk; > > class bar {} > ?> > > Would start failing too once you merge them in one file, even though > they worked just fine before.
Right, that's why I was saying expansion of imports would be necessary, meaning that all references to "bar" would need to be translated to "otherfoo::bar" If this is a huge problem, it could be solved by having a separate import scope within namespace brackets. This is accomplished easily by storing the existing CG(current_import) in a temp variable, CG(saved_import), resetting CG(current_import) to NULL to start over at the namespace declaration, and then restoring the old import list via CG(current_import) = CG(saved_import) and freeing CG(saved_import). This would of course mean that top-level import is not the same as import within a namespace, would that make sense? I've attached an updated patch to reflect this (it adds 9 lines and a new test for the approach, ns_046.phpt). Please note that I am not so sure I like this approach, and I have not deleted the original patch (at http://pear.php.net/~greg/namespaces.patch.txt). The new patch is also at http://pear.php.net/~greg/namespaces_smartimport.patch.txt Greg

Stanislav Malyshev

19 years ago
> Right, that's why I was saying expansion of imports would be necessary, > meaning that all references to "bar" would need to be translated to > "otherfoo::bar"
Thatnslated by whom? How? I'm not sure I understand.
> CG(current_import) = CG(saved_import) and freeing CG(saved_import). > This would of course mean that top-level import is not the same as > import within a namespace, would that make sense?
Not really, but that's the only way to make it work with any kind of consistency. That's why I'm saying this thing is more complex that it appears at the first glance.
-- Stanislav Malyshev, Zend Software Architect stas@zend.com http://www.zend.com/ (408)253-8829 MSN: stas@zend.com