# Importing namespaced functions

- Thread: https://externals.io/message/67097
- Original archive: https://news-web.php.net/php.internals/67097
- Started by Igor Wiedler on 2013-04-19T02:24:09+00:00
- Messages: 18
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #67097 — Igor Wiedler — 2013-04-19T02:24:09+00:00

URL: https://externals.io/message/67097#67097

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

---

## #67098 — Stas Malyshev — 2013-04-19T06:19:36+00:00

URL: https://externals.io/message/67097#67098 · In reply to: #67097

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

---

## #67099 — crosse@2bepublished@Christoph Rosse — 2013-04-19T13:48:05+00:00

URL: https://externals.io/message/67097#67099 · In reply to: #67098

> Hi!
>
> > […]
>
> 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

---

## #67100 — Robert Stoll — 2013-04-19T14:09:54+00:00

URL: https://externals.io/message/67097#67100 · In reply to: #67099

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!
>
> > […]
>
> 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

---

## #67102 — Igor Wiedler — 2013-04-21T03:00:03+00:00

URL: https://externals.io/message/67097#67102 · In reply to: #67098

> 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.

---

## #67104 — Igor Wiedler — 2013-04-21T22:36:15+00:00

URL: https://externals.io/message/67097#67104 · In reply to: #67102

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

---

## #67105 — Robert Stoll — 2013-04-21T22:55:40+00:00

URL: https://externals.io/message/67097#67105 · In reply to: #67104

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

---

## #67106 — Florian Anderiasch — 2013-04-22T08:00:28+00:00

URL: https://externals.io/message/67097#67106 · In reply to: #67105

> 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

---

## #67114 — Daniele Orlando — 2013-04-23T19:28:54+00:00

URL: https://externals.io/message/67097#67114 · In reply to: #67106

+1

The current behavior is really annoying.


2013/4/22 Florian Anderiasch <ml@anderiasch.de>

> 
> > […]
>
> 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

---

## #67118 — Martin Keckeis — 2013-04-24T06:15:00+00:00

URL: https://externals.io/message/67097#67118 · In reply to: #67114

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>
>
> > […]
> the
> > […]
> recommend
> > […]
> or
> > […]
> is
> > […]
> normal
> > […]

---

## #67119 — Florian Anderiasch — 2013-04-24T08:54:04+00:00

URL: https://externals.io/message/67097#67119 · In reply to: #67118

> 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

---

## #67120 — Alexander Deruwe — 2013-04-24T09:03:23+00:00

URL: https://externals.io/message/67097#67120 · In reply to: #67119

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

---

## #67273 — Igor Wiedler — 2013-05-02T20:44:50+00:00

URL: https://externals.io/message/67097#67273 · In reply to: #67097

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

---

## #67275 — Sebastian Krebs — 2013-05-02T21:40:17+00:00

URL: https://externals.io/message/67097#67275 · In reply to: #67273

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
> --
> 
> 
>
>


-- 
github.com/KingCrunch

---

## #67276 — Igor Wiedler — 2013-05-02T21:55:25+00:00

URL: https://externals.io/message/67097#67276 · In reply to: #67275

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

---

## #67278 — Sebastian Krebs — 2013-05-02T22:18:09+00:00

URL: https://externals.io/message/67097#67278 · In reply to: #67276

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





>
> 
>
> > […]
>



-- 
github.com/KingCrunch

---

## #67280 — Igor Wiedler — 2013-05-02T23:51:36+00:00

URL: https://externals.io/message/67097#67280 · In reply to: #67278

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,
> Sebastian
> 
> 
> 
>  
> 
> 
> 
> > […]
> 
> 
> 
> -- 
> github.com/KingCrunch

---

## #67426 — Yasuo Ohgaki — 2013-05-15T04:26:21+00:00

URL: https://externals.io/message/67097#67426 · In reply to: #67280

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
>
> 
>
> > […]
> now?
> > […]
> class-autoloading.
> > […]
> | AUTOLOAD_CONSTANT); // "constant" here just to make it complete
> > […]
> especially because it isn't such a big deal to simply use the prefixed one,
> so the benefit seems quite small to me :X
> > […]
> wrote:
> > […]
