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
Thanks. someone please commit that as fast as posible so no one can say anything
;-)
Hi all,
This patch is also available at
http://pear.php.net/~greg/namespace.patch.txtThe 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
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:
Thanks. someone please commit that as fast as posible so no one can say anything
;-)
Hi all,
This patch is also available at
http://pear.php.net/~greg/namespace.patch.txtThe 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
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:
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:
Thanks. someone please commit that as fast as posible so no one can
say anything;-)
Hi all,
This patch is also available at
http://pear.php.net/~greg/namespace.patch.txtThe 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
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
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 bracketsRasmus 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
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
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 bracketsGregory 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
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
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
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
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.
Hi all,
This patch is also available at
http://pear.php.net/~greg/namespace.patch.txtThe 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
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
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
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:
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
<?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
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
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 bracketsHi all,
This patch is also available at
http://pear.php.net/~greg/namespace.patch.txtThe 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
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 bracketsHi all,
This patch is also available at
http://pear.php.net/~greg/namespace.patch.txtThe 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
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
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,
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 - 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
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
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
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
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!
...........................................................
Robert Cummings 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 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!
...........................................................
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
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
Stanislav Malyshev wrote:
that if you try to "combine" two files that contain import statements,
it will be necessary to expand the imports. Fortunately, sinceWhat 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
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
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
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