Hello internals,
One of the shortcomings of namespaced functions in PHP is that it is not possible to import them as you can do with classes and namespaces. For code that is not in the same namespace as the function, you must always reference at least one part of the namespace in order to call it.
It would help a lot if functions could be imported as well. I have drafted an RFC that tries to address this and wanted to get some initial feedback on the idea:
https://gist.github.com/igorw/44133fe2feb0c1a5d51f
Thanks!
Igor
Hi!
One of the shortcomings of namespaced functions in PHP is that it is
not possible to import them as you can do with classes and
namespaces. For code that is not in the same namespace as the
function, you must always reference at least one part of the
namespace in order to call it.
What's wrong with referencing one part of it? It can be as short as two
characters, and an an added bonus you won't suddenly have your strlen
overridden by somebody without you knowing it. Functions live in global
space, and there's a real lot of them, that's why importing them wasn't
considered a good idea - it's going back to the same problem we were
escaping with namespaces.
Saving two keystrokes while sacrificing clarity is usually not the best
idea.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
One of the shortcomings of namespaced functions in PHP is that it is
not possible to import them as you can do with classes and
namespaces. For code that is not in the same namespace as the
function, you must always reference at least one part of the
namespace in order to call it.What's wrong with referencing one part of it? It can be as short as two
characters, and an an added bonus you won't suddenly have your strlen
overridden by somebody without you knowing it. Functions live in global
space, and there's a real lot of them, that's why importing them wasn't
considered a good idea - it's going back to the same problem we were
escaping with namespaces.Saving two keystrokes while sacrificing clarity is usually not the best
idea.
I don't know about your libraries but mine use longer namespace parts
then 2 charakters.
And strlen wouldn't be "suddenly" overridden because you would have to
explicitly import it, so this argument could be used for namespaces too
because if I "use some\ns\DateTime" DateTime is "suddenly" overridden.
--
Christoph Rosse
Softwaredevelopment | Operations
2bePUBLISHED Internet Services Austria GmbH
Brünner Straße 85/2, 1210 Wien
Tel.: 0043.1.9971500
Fax.: 0043.1.997150066
E-mail: crosse@2bepublished.at
Skype: christoph.rosse
Home: http://www.2bepublished.at
You can import a namespace and use an alias. For instance
use com\example\cms as c;
c\foo();
-----Ursprüngliche Nachricht-----
Von: Christoph Rosse [mailto:crosse@2bepublished.at]
Gesendet: Freitag, 19. April 2013 14:48
An: internals@lists.php.net
Betreff: Re: [PHP-DEV] Importing namespaced functions
Hi!
One of the shortcomings of namespaced functions in PHP is that it is
not possible to import them as you can do with classes and
namespaces. For code that is not in the same namespace as the
function, you must always reference at least one part of the
namespace in order to call it.What's wrong with referencing one part of it? It can be as short as
two characters, and an an added bonus you won't suddenly have your
strlen overridden by somebody without you knowing it. Functions live
in global space, and there's a real lot of them, that's why importing
them wasn't considered a good idea - it's going back to the same
problem we were escaping with namespaces.Saving two keystrokes while sacrificing clarity is usually not the
best idea.
I don't know about your libraries but mine use longer namespace parts then 2
charakters.
And strlen wouldn't be "suddenly" overridden because you would have to
explicitly import it, so this argument could be used for namespaces too
because if I "use some\ns\DateTime" DateTime is "suddenly" overridden.
--
Christoph Rosse
Softwaredevelopment | Operations
2bePUBLISHED Internet Services Austria GmbH Brünner Straße 85/2, 1210 Wien
Tel.: 0043.1.9971500
Fax.: 0043.1.997150066
E-mail: crosse@2bepublished.at
Skype: christoph.rosse
Home: http://www.2bepublished.at
--
To unsubscribe, visit:
http://www.php.net/unsub.php
What's wrong with referencing one part of it? It can be as short as two
characters, and an an added bonus you won't suddenly have your strlen
overridden by somebody without you knowing it. Functions live in global
space, and there's a real lot of them, that's why importing them wasn't
considered a good idea - it's going back to the same problem we were
escaping with namespaces.Saving two keystrokes while sacrificing clarity is usually not the best
idea.
The same argument could be made for classes. Why import them if you can just
import the namespace? I think it reduces noise and allows imported functions
to be treated as an extension of the language. Without polluting the global
namespace.
As it stands, functions are a second class citizen in PHP. It is harder to use
them due to arbitrary restrictions that don't apply to classes.
Let me give you two specific cases where I think importing a function
significantly improves the readability of code.
A) Tiny libraries
I recently released a "library" that really just consists of two functions.
Those functions are named compose() and pipeline(), and the library is named
"igorw/compose". I didn't want to risk conflicts in the global namespace, so I
just put them in the "igorw" namespace.
Now users need to do this:
$x = igorw\compose('foo', 'bar', 'baz');
It's distracting to have my vendor name in there every time they call the
function. They can alias it, but then they just need to come up with a random
word that makes no sense.
compose\compose(...);
c\compose(...);
foo\compose(...);
B) Domain specific languages
I hope I'm not mis-using the term "DSL" here, so just let me explain what I
mean. When building some kind of representation of something, it can sometimes
be quite nice to have a set of functions representing the elements, and nest
those calls.
An example of this could be building HTML (you can apply it to building
workflows, business rules, graphs, configuration, etc).
use html\div, html\p, html\em;
$html = div(p('Some', em('Text')));
Having to prefix the namespace in either of these cases leads to a lot of
noise. Hopefully that gives you a better idea of where I'm coming from.
Regards,
Igor
I agree with Igor. The readability could be improved and I do not see the
problem of hiding built-in php functions (however, I would not recommend
it).
I would say, if someone hides the normal php built-in function then he or
she is doing that on purpose and is aware of the consequences. Thus it is
also fine if the same person imports the function, which hides the normal
php built-in function, in another namespace.
-----Ursprüngliche Nachricht-----
Von: Igor Wiedler [mailto:igor@wiedler.ch]
Gesendet: Sonntag, 21. April 2013 23:36
An: internals@lists.php.net
Betreff: Re: [PHP-DEV] Importing namespaced functions
Let me give you two specific cases where I think importing a function
significantly improves the readability of code.
A) Tiny libraries
I recently released a "library" that really just consists of two functions.
Those functions are named compose() and pipeline(), and the library is named
"igorw/compose". I didn't want to risk conflicts in the global namespace, so
I just put them in the "igorw" namespace.
Now users need to do this:
$x = igorw\compose('foo', 'bar', 'baz');
It's distracting to have my vendor name in there every time they call the
function. They can alias it, but then they just need to come up with a
random word that makes no sense.
compose\compose(...);
c\compose(...);
foo\compose(...);
B) Domain specific languages
I hope I'm not mis-using the term "DSL" here, so just let me explain what I
mean. When building some kind of representation of something, it can
sometimes be quite nice to have a set of functions representing the
elements, and nest those calls.
An example of this could be building HTML (you can apply it to building
workflows, business rules, graphs, configuration, etc).
use html\div, html\p, html\em;
$html = div(p('Some', em('Text')));
Having to prefix the namespace in either of these cases leads to a lot of
noise. Hopefully that gives you a better idea of where I'm coming from.
Regards,
Igor
--
To unsubscribe, visit:
http://www.php.net/unsub.php
I agree with Igor. The readability could be improved and I do not see the
problem of hiding built-in php functions (however, I would not recommend
it).
I would say, if someone hides the normal php built-in function then he or
she is doing that on purpose and is aware of the consequences. Thus it is
also fine if the same person imports the function, which hides the normal
php built-in function, in another namespace.
Huge +1 from me.
I know that using only functions instead of OOP in PHP has this
90s-PHP3-Vibe to it, but as a matter of fact you can write mostly
side-effect free code using only functions in PHP.
This would make using functions much more flexible and even more
importantly, consistent to everything else.
The only downside to this proposal, as Stas correctly mentioned is that
it would allow people to shoot themselves in the foot when using weird
import behavior. But as you deliberately have to misuse this I don't see
any real harm. Something like instance variable shadowing in Java is
much, much more error-prone and still hardly anyone complains about this
kind of feature.
Greetings,
Florian
+1
The current behavior is really annoying.
2013/4/22 Florian Anderiasch ml@anderiasch.de
I agree with Igor. The readability could be improved and I do not see the
problem of hiding built-in php functions (however, I would not recommend
it).
I would say, if someone hides the normal php built-in function then he or
she is doing that on purpose and is aware of the consequences. Thus it is
also fine if the same person imports the function, which hides the normal
php built-in function, in another namespace.Huge +1 from me.
I know that using only functions instead of OOP in PHP has this
90s-PHP3-Vibe to it, but as a matter of fact you can write mostly
side-effect free code using only functions in PHP.This would make using functions much more flexible and even more
importantly, consistent to everything else.The only downside to this proposal, as Stas correctly mentioned is that
it would allow people to shoot themselves in the foot when using weird
import behavior. But as you deliberately have to misuse this I don't see
any real harm. Something like instance variable shadowing in Java is
much, much more error-prone and still hardly anyone complains about this
kind of feature.Greetings,
Florian
Hello together,
if you got a namespace with more than one functions, why not just create a
container class and make the methods static?
I know it's not exactly the same, but how many times you need this....
So you can write:
namespace Abc\Def;
class Something{
public static function blubb();
public static function blubb2();
}
use Abc\Def\Something;
Something::blubb();
Something::blubb2();
Best regards
Martin
2013/4/23 Daniele Orlando dnl.rlnd@gmail.com
+1
The current behavior is really annoying.
2013/4/22 Florian Anderiasch ml@anderiasch.de
I agree with Igor. The readability could be improved and I do not see
the
problem of hiding built-in php functions (however, I would not
recommend
it).
I would say, if someone hides the normal php built-in function then he
or
she is doing that on purpose and is aware of the consequences. Thus it
is
also fine if the same person imports the function, which hides the
normal
php built-in function, in another namespace.Huge +1 from me.
I know that using only functions instead of OOP in PHP has this
90s-PHP3-Vibe to it, but as a matter of fact you can write mostly
side-effect free code using only functions in PHP.This would make using functions much more flexible and even more
importantly, consistent to everything else.The only downside to this proposal, as Stas correctly mentioned is that
it would allow people to shoot themselves in the foot when using weird
import behavior. But as you deliberately have to misuse this I don't see
any real harm. Something like instance variable shadowing in Java is
much, much more error-prone and still hardly anyone complains about this
kind of feature.Greetings,
Florian
class Something{
public static function blubb();public static function blubb2();
}
use Abc\Def\Something;
Something::blubb();
Something::blubb2();
Yes of course you can do that as an ugly workaround - but I wouldn't
call that a good reason to treat functions differently than classes.
This is just a gut feeling, but maybe Reflection stuff even differs for
methods and functions. Would be interesting to compare memory footprint
and execution speed of function vs. static method as well. (Do we even
have some sort of general knowledge on this? Can anyone give (relative)
numbers?)
Additionally, it's either semantically wrong to group unrelated
functions in "static tool classes", it's even a well-known antipattern.
Greetings,
Florian
On Wed, Apr 24, 2013 at 10:54 AM, Florian Anderiasch ml@anderiasch.de
wrote:
Additionally, it's either semantically wrong to group unrelated
functions in "static tool classes", it's even a well-known antipattern.
It also doesn't address a point made by Igor before:
"It's distracting to have my vendor name in there every time they call the
function. They can alias it, but then they just need to come up with a
random
word that makes no sense."
The difference being that now it's not a vendor name but a class name.
Alexander
Hi internals,
Since there's been no major objection to this proposed RFC, I will go ahead and create it on the wiki. I will amend it to address some of the points that were discussed so far.
Thanks,
Igor
Hi,
Are you going to cover autoloading of functions too?
Regards,
Sebastian
2013/5/2 Igor Wiedler igor@wiedler.ch
Hi internals,
Since there's been no major objection to this proposed RFC, I will go
ahead and create it on the wiki. I will amend it to address some of the
points that were discussed so far.Thanks,
Igor
No, I want to keep autoloading out of this proposal. It is way beyond the scope of the namespacing issue and also incredibly complex.
That said, this RFC may be useful for implementing autoloading in the future, as it addresses one of the things that makes function autoloading hard, which is being able to distinguish between namespaced and global function calls. But that's only one piece of the puzzle.
Hi,
Are you going to cover autoloading of functions too?
Regards,
Sebastian
2013/5/2 Igor Wiedler igor@wiedler.ch
No, I want to keep autoloading out of this proposal. It is way beyond the
scope of the namespacing issue and also incredibly complex.That said, this RFC may be useful for implementing autoloading in the
future, as it addresses one of the things that makes function autoloading
hard, which is being able to distinguish between namespaced and global
function calls. But that's only one piece of the puzzle.
Well, it is not as complex as it sounds
This is the behaviour right now
- Does X exists as namespaced function (current namespace or imported)?
- Does X exists as global (builtin) function?
- Trigger error
The behaviour including autoloading would be more like
- Does X exists as namespaced function (current namespace or imported)?
- Does X exists as global (builtin) function?
- Trigger autoload
- Does X exists as namespaced function (current namespace or imported) now?
- Maybe: Does X exists as global function now?
- Trigger error
The autoloading itself could use parts already used for class-autoloading.
// Signature
// spl_autoload_register($callback[, $type = AUTOLOAD_CLASS]);
$autoload = function ($name, $type = AUTOLOAD_CLASS) {
// Do something
};
spl_autoload_register($autoload, AUTOLOAD_CLASS | AUTOLOAD_FUNCTION |
AUTOLOAD_CONSTANT); // "constant" here just to make it complete
Namespaced functions without autoloading seems kindof incomplete,
especially because it isn't such a big deal to simply use the prefixed one,
so the benefit seems quite small to me :X
use MyFoo\Bar\MathFunctions as math;
$x = math\sin($y);
Just saying :)
Regards,
Sebastian
Hi,
Are you going to cover autoloading of functions too?
Regards,
Sebastian
Your solution is flawed, it would not allow autoloading a function that has the same
(namespaced) name as a builtin.
Example:
// autoloadable function
namespace foo {
// make arg order consistent
function array_filter($callback, $input) {
return \array_filter($input, $callback);
}
function is_positive($x) {
return $x > 0;
}
}
namespace foo {
var_dump(array_filter('foo\is_positive', [-2, -1, 0, 1, 2]));
}
Always triggering the autoloader is not feasible either, as it will lead to tons of stat calls,
one per namespace that any global function is called in.
Potential solutions: Only autoload fully qualified or imported functions.
But there is lots of potential for bikeshedding there, plus it requires more implementation
effort, and quite possibly more performance and cache related considerations that I am
not aware of.
As much as I would like to see function autoloading, I don't think bundling the proposals
is going to be beneficial. Which is why I'd rather just focus on one issue at a time.
Regards,
Igor
Well, it is not as complex as it sounds
This is the behaviour right now
- Does X exists as namespaced function (current namespace or imported)?
- Does X exists as global (builtin) function?
- Trigger error
The behaviour including autoloading would be more like
- Does X exists as namespaced function (current namespace or imported)?
- Does X exists as global (builtin) function?
- Trigger autoload
- Does X exists as namespaced function (current namespace or imported) now?
- Maybe: Does X exists as global function now?
- Trigger error
The autoloading itself could use parts already used for class-autoloading.
// Signature // spl_autoload_register($callback[, $type = AUTOLOAD_CLASS]); $autoload = function ($name, $type = AUTOLOAD_CLASS) { // Do something }; spl_autoload_register($autoload, AUTOLOAD_CLASS | AUTOLOAD_FUNCTION | AUTOLOAD_CONSTANT); // "constant" here just to make it complete
Namespaced functions without autoloading seems kindof incomplete, especially because it isn't such a big deal to simply use the prefixed one, so the benefit seems quite small to me :X
use MyFoo\Bar\MathFunctions as math; $x = math\sin($y);
Just saying :)
Regards,
SebastianHi,
Are you going to cover autoloading of functions too?
Regards,
Sebastian
Hi,
Although this change may cause confusion, but it would be beneficial to
many users as a security counter measure.
For instance, there is CVE-2013-2065 for Ruby
http://www.ruby-lang.org/en/news/2013/05/14/taint-bypass-dl-fiddle-cve-2013-2065/
I suppose this change allow us "monkey patch" PHP without upgrade if it is
needed.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
2013/5/3 Igor Wiedler igor@wiedler.ch
Your solution is flawed, it would not allow autoloading a function that
has the same
(namespaced) name as a builtin.Example:
// autoloadable function namespace foo { // make arg order consistent function array_filter($callback, $input) { return \array_filter($input, $callback); } function is_positive($x) { return $x > 0; } } namespace foo { var_dump(array_filter('foo\is_positive', [-2, -1, 0, 1, 2])); }
Always triggering the autoloader is not feasible either, as it will lead
to tons of stat calls,
one per namespace that any global function is called in.Potential solutions: Only autoload fully qualified or imported functions.
But there is lots of potential for bikeshedding there, plus it requires
more implementation
effort, and quite possibly more performance and cache related
considerations that I am
not aware of.As much as I would like to see function autoloading, I don't think
bundling the proposals
is going to be beneficial. Which is why I'd rather just focus on one issue
at a time.Regards,
Igor
Well, it is not as complex as it sounds
This is the behaviour right now
- Does X exists as namespaced function (current namespace or imported)?
- Does X exists as global (builtin) function?
- Trigger error
The behaviour including autoloading would be more like
- Does X exists as namespaced function (current namespace or imported)?
- Does X exists as global (builtin) function?
- Trigger autoload
- Does X exists as namespaced function (current namespace or imported)
now?- Maybe: Does X exists as global function now?
- Trigger error
The autoloading itself could use parts already used for
class-autoloading.// Signature // spl_autoload_register($callback[, $type = AUTOLOAD_CLASS]); $autoload = function ($name, $type = AUTOLOAD_CLASS) { // Do something }; spl_autoload_register($autoload, AUTOLOAD_CLASS | AUTOLOAD_FUNCTION
| AUTOLOAD_CONSTANT); // "constant" here just to make it complete
Namespaced functions without autoloading seems kindof incomplete,
especially because it isn't such a big deal to simply use the prefixed one,
so the benefit seems quite small to me :Xuse MyFoo\Bar\MathFunctions as math; $x = math\sin($y);
Just saying :)
Regards,
SebastianOn May 2, 2013, at 11:40 PM, Sebastian Krebs krebs.seb@gmail.com
wrote:Hi,
Are you going to cover autoloading of functions too?
Regards,
Sebastian