# Not autoloading functions

- Thread: https://externals.io/message/97888
- Original archive: https://news-web.php.net/php.internals/97888
- Started by Rasmus Schultz on 2017-01-20T07:04:44+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

---

## #97888 — Rasmus Schultz — 2017-01-20T07:04:44+00:00

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

Just a quick thought.

Since the autoloading functions proposal is stalled, how about allowing for
import of static functions instead?

    use function Foo::bar;

    bar(); // calls Foo::bar()

There are two benefits to this approach:

1. There is immediate support for autoloading without any need for adoption
or support in existing autoloaders.

2. Pseudo-namespaces (abstract classes with stateless static functions) are
already widely practiced in PHP - a lot of existing code would be supported
as is.

The syntax when calling functions would be the same.

If we had function autoloading, we would likely collect related functions
in a file anyway - putting them in a class instead gives more less the same
exact result.

The only drawback I can see, is the inability to import a whole set of
functions with one statement - but being explicit about external imports is
widely considered best practice for classes and interfaces, so why not for
functions. Yeah, it's a bit inconvenient, but at least we can move ahead
and leverage existing code without changes or BC breaks. It's not all bad.
It's better than nothing perhaps? :-)

Thoughts?

---

## #97895 — Fleshgrinder — 2017-01-20T18:00:29+00:00

URL: https://externals.io/message/97888#97895 · In reply to: #97888

> Just a quick thought.
> 
> Since the autoloading functions proposal is stalled, how about allowing for
> import of static functions instead?
> 
>     use function Foo::bar;
> 
>     bar(); // calls Foo::bar()
> 
> There are two benefits to this approach:
> 
> 1. There is immediate support for autoloading without any need for adoption
> or support in existing autoloaders.
> 
> 2. Pseudo-namespaces (abstract classes with stateless static functions) are
> already widely practiced in PHP - a lot of existing code would be supported
> as is.
> 
> The syntax when calling functions would be the same.
> 
> If we had function autoloading, we would likely collect related functions
> in a file anyway - putting them in a class instead gives more less the same
> exact result.
> 
> The only drawback I can see, is the inability to import a whole set of
> functions with one statement - but being explicit about external imports is
> widely considered best practice for classes and interfaces, so why not for
> functions. Yeah, it's a bit inconvenient, but at least we can move ahead
> and leverage existing code without changes or BC breaks. It's not all bad.
> It's better than nothing perhaps? :-)
> 
> Thoughts?
> 

I actually like this idea a lot, something similar is possible in Rust
with Enums.

```rust
pub use self::Foo::{A, B};

pub enum Foo {
    A,
    B
}

fn main() {
    let a = A;
}
```

Loading a set of static methods could look similar.

```php
final class Foo {
    public static function A(): self {
        return new self;
    }

    public static function B(): self {
        return new self;
    }
}
```

```php
use function Foo::{A, B};

$a = A();
```

-- 
Richard "Fleshgrinder" Fussenegger

---

## #97896 — Paul Jones — 2017-01-20T18:15:12+00:00

URL: https://externals.io/message/97888#97896 · In reply to: #97888

> 
> 
> Just a quick thought.
> 
> Since the autoloading functions proposal is stalled, how about allowing for
> import of static functions instead?
> 
>    use function Foo::bar;
> 
>    bar(); // calls Foo::bar()
> 
...
> at least we can move ahead
> and leverage existing code without changes or BC breaks. It's not all bad.
> It's better than nothing perhaps? :-)

I find this intuitively appealing. It's an incremental change with tangible benefit in an imaginable timeframe, as vs a dramatic change in an unknowable timeframe.

However, I am not an internals expert, so I'll leave it to them to say how big a deal it would be to implement, and what the drawbacks are.


-- 
Paul M. Jones
pmjones88@gmail.com
http://paul-m-jones.com

Modernizing Legacy Applications in PHP
https://leanpub.com/mlaphp

Solving the N+1 Problem in PHP
https://leanpub.com/sn1php

---

## #97897 — Stanislav Malyshev — 2017-01-20T18:55:51+00:00

URL: https://externals.io/message/97888#97897 · In reply to: #97888

Hi!

> Since the autoloading functions proposal is stalled, how about allowing for
> import of static functions instead?
> 
>     use function Foo::bar;
> 
>     bar(); // calls Foo::bar()

I'm not sure why it is good. This would certainly be confusing, if you
call strlen and turns out it's completely different function from what
you thought. One thing when it's the same namespace, at least you can be
aware what this package does, but if it's just an arbitrary function
from anywhere, it's really bad for understanding the code.

How hard is it to write Foo::bar? You never have to go more
than one level. I don't see a point in mixing internal function
namespace with class methods for the sake of saving typing couple of
characters.

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #97898 — Nikita Popov — 2017-01-20T18:58:26+00:00

URL: https://externals.io/message/97888#97898 · In reply to: #97897

On Fri, Jan 20, 2017 at 7:55 PM, Stanislav Malyshev <smalyshev@gmail.com>
wrote:

> Hi!
>
> > […]
> for
> > […]
>
> I'm not sure why it is good. This would certainly be confusing, if you
> call strlen and turns out it's completely different function from what
> you thought. One thing when it's the same namespace, at least you can be
> aware what this package does, but if it's just an arbitrary function
> from anywhere, it's really bad for understanding the code.
>

How is that different from the already existing "use function foo\bar\baz
as strlen"?


> How hard is it to write Foo::bar? You never have to go more
> than one level. I don't see a point in mixing internal function
> namespace with class methods for the sake of saving typing couple of
> characters.
>
> --
> Stas Malyshev
> smalyshev@gmail.com

---

## #97899 — Fleshgrinder — 2017-01-20T19:30:44+00:00

URL: https://externals.io/message/97888#97899 · In reply to: #97898

> On Fri, Jan 20, 2017 at 7:55 PM, Stanislav Malyshev <smalyshev@gmail.com>
> wrote:
> 
> > […]
> 
> How is that different from the already existing "use function foo\bar\baz
> as strlen"?
> 

Or any other function that has no namespace separator in front.

```
<?php

namespace Fleshgrinder\Examples;

function strlen($string) {
    return 42; // Troll! =)
}

final class SomeClass {

    public function __construct() {
        echo strlen('f');
    }

}

new SomeClass;

```

This is actually used by some in tests to provoke error conditions in
built-in PHP functions to verify their error handling.

-- 
Richard "Fleshgrinder" Fussenegger

---

## #97910 — Rasmus Schultz — 2017-01-21T08:14:39+00:00

URL: https://externals.io/message/97888#97910 · In reply to: #97897

> How hard is it to write Foo::bar? You never have to go more
than one level. I don't see a point in mixing internal function
namespace with class methods for the sake of saving typing couple of
characters.

I'm not suggesting we mix namespaces - this of course would be file-local,
same as use-statements in general.

You likely have to write a use-statement either way, if you're going to
call a static function, e.g.:

use Foo\Bar\HtmlHelper;
echo HtmlHelper::escape($text);

Versus:

use Foo\Bar\HtmlHelper::escape;
echo escape($text);

It's not about "saving characters", that's not what use-statements are for
- it's to avoid qualifying the same references repeatedly, which (for one)
is better for source-control, whether that's a namespace or a class-name
being repeated.

Anyhow, it sounds like most of you are positive about this idea, so I will
ponder the details and post a small RFC :-)




Hi!

> Since the autoloading functions proposal is stalled, how about allowing
for
> import of static functions instead?
>
>     use function Foo::bar;
>
>     bar(); // calls Foo::bar()

I'm not sure why it is good. This would certainly be confusing, if you
call strlen and turns out it's completely different function from what
you thought. One thing when it's the same namespace, at least you can be
aware what this package does, but if it's just an arbitrary function
from anywhere, it's really bad for understanding the code.

How hard is it to write Foo::bar? You never have to go more
than one level. I don't see a point in mixing internal function
namespace with class methods for the sake of saving typing couple of
characters.

--
Stas Malyshev
smalyshev@gmail.com

---

## #97914 — Marcio Almada — 2017-01-21T14:53:25+00:00

URL: https://externals.io/message/97888#97914 · In reply to: #97910

Hi, Rasmus!

2017-01-21 4:14 GMT-04:00 Rasmus Schultz <rasmus@mindplay.dk>:

> > […]
> than one level. I don't see a point in mixing internal function
> namespace with class methods for the sake of saving typing couple of
> characters.
>
> I'm not suggesting we mix namespaces - this of course would be file-local,
> same as use-statements in general.
>
> You likely have to write a use-statement either way, if you're going to
> call a static function, e.g.:
>
> use Foo\Bar\HtmlHelper;
> echo HtmlHelper::escape($text);
>
> Versus:
>
> use Foo\Bar\HtmlHelper::escape;
> echo escape($text);
>
> It's not about "saving characters", that's not what use-statements are for
> - it's to avoid qualifying the same references repeatedly, which (for one)
> is better for source-control, whether that's a namespace or a class-name
> being repeated.
>
> Anyhow, it sounds like most of you are positive about this idea, so I will
> ponder the details and post a small RFC :-)
>
>
> 
>
> Hi!
>
> > […]
> for
> > […]
>
> I'm not sure why it is good. This would certainly be confusing, if you
> call strlen and turns out it's completely different function from what
> you thought. One thing when it's the same namespace, at least you can be
> aware what this package does, but if it's just an arbitrary function
> from anywhere, it's really bad for understanding the code.
>
> How hard is it to write Foo::bar? You never have to go more
> than one level. I don't see a point in mixing internal function
> namespace with class methods for the sake of saving typing couple of
> characters.
>
> --
> Stas Malyshev
> smalyshev@gmail.com
>

I think this idea looks like the easiest way to avoid fixing the underlying
problem. But it would irrevocably push
functions to a "second class citizenship" of the language, in favor of
static classes. It also would blurry
the lines between namespaces and classes in a way we haven't seen before.

Even though it feels pragmatic to do so, I'd prefer the harder path or at
least wait for the next major until commit to this.

Thanks,
Márcio.

---

## #97967 — Andrea Faulds — 2017-01-26T09:04:37+00:00

URL: https://externals.io/message/97888#97967 · In reply to: #97888

Hi,

Rasmus Schultz wrote:
> Since the autoloading functions proposal is stalled, how about allowing for
> import of static functions instead?

The problem with stop-gap measures is they become entrenched, and the 
proper solution doesn't get implemented. But we may be at the risk of 
the latter anyway.

-- 
Andrea Faulds
https://ajf.me/

---

## #97968 — Niklas Keller — 2017-01-26T09:46:44+00:00

URL: https://externals.io/message/97888#97968 · In reply to: #97888

>
> Since the autoloading functions proposal is stalled, how about allowing for
> import of static functions instead?
>
>     use function Foo::bar;
>
>     bar(); // calls Foo::bar()
>
> There are two benefits to this approach:
>
> 1. There is immediate support for autoloading without any need for adoption
> or support in existing autoloaders.
>

It adds "support". Just use a static method then instead of inventing some
new alias system.


> 2. Pseudo-namespaces (abstract classes with stateless static functions) are
> already widely practiced in PHP - a lot of existing code would be supported
> as is.
>

That same code is already supported, no need for a language change here.


> The syntax when calling functions would be the same.
>
> If we had function autoloading, we would likely collect related functions
> in a file anyway - putting them in a class instead gives more less the same
> exact result.
>
> The only drawback I can see, is the inability to import a whole set of
> functions with one statement - but being explicit about external imports is
> widely considered best practice for classes and interfaces, so why not for
> functions.


Just import the class and you're fine, you have just imported a group of
functions.


> Yeah, it's a bit inconvenient, but at least we can move ahead
> and leverage existing code without changes or BC breaks. It's not all bad.
> It's better than nothing perhaps? :-)
>
> Thoughts?
>

I don't see any benefits here, just drawbacks. It adds yet another alias
system, function calls can now be function calls and static methods. What's
with the static scope? It gets lost here. Nothing shows there's a static
scope.

Strong -1 from me, sorry.

Regards, Niklas

---

## #97969 — Nikita Popov — 2017-01-26T10:21:37+00:00

URL: https://externals.io/message/97888#97969 · In reply to: #97968

> > […]
> for
> > […]
> adoption
> > […]
>
> It adds "support". Just use a static method then instead of inventing some
> new alias system.
>
>
> > […]
> are
> > […]
> supported
> > […]
>
> That same code is already supported, no need for a language change here.
>
>
> > […]
> same
> > […]
> is
> > […]
> for
> > […]
>
>
> Just import the class and you're fine, you have just imported a group of
> functions.
>
>
> > […]
> bad.
> > […]
>
> I don't see any benefits here, just drawbacks. It adds yet another alias
> system, function calls can now be function calls and static methods. What's
> with the static scope? It gets lost here. Nothing shows there's a static
> scope.
>

A question in conjunction with this: How would this call actually treat the
LSB and $this scope? Would it follow the normal rules for scoped method
calls, or prevent adoption of scopes? For example:

use A::__construct as ctor;
class A { public function __construct() {} }
class B extends A { public function __construct() { ctor(); } }

Would this become an alternative way of writing parent::__construct() in B?
Would it behave the same?

Nikita

---

## #97970 — Rasmus Schultz — 2017-01-26T16:52:22+00:00

URL: https://externals.io/message/97888#97970 · In reply to: #97967

> The problem with stop-gap measures is they become entrenched, and the
proper solution doesn't get implemented

This would be my general point of view - unfortunately, functions are
essentially useless at present, in a world with Composer, unless you're
willing to preload all functions from all packages up-front.

The only suggested solutions I've heard for the name resolution issue with
function autoloading frankly are all horrible - much worse than this simple
alternative.

Add to that the fact that likely 90% of all functions in the wild (at least
in Composer packages) are currently implemented as public static functions,
and in my opinion, this is starting to sound less like a stop-gap and more
like a simple solution to a problem we've been solving with a stop-gap for,
oh, 10 years or so...




> Hi,
>
> Rasmus Schultz wrote:
>
> > […]
>
> The problem with stop-gap measures is they become entrenched, and the
> proper solution doesn't get implemented. But we may be at the risk of the
> latter anyway.
>
> --
> Andrea Faulds
> https://ajf.me/

---

## #97972 — Niklas Keller — 2017-01-26T17:50:01+00:00

URL: https://externals.io/message/97888#97972 · In reply to: #97970

>
> > […]
> proper solution doesn't get implemented
>
> This would be my general point of view - unfortunately, functions are
> essentially useless at present, in a world with Composer, unless you're
> willing to preload all functions from all packages up-front.
>
> The only suggested solutions I've heard for the name resolution issue with
> function autoloading frankly are all horrible - much worse than this simple
> alternative.
>
> Add to that the fact that likely 90% of all functions in the wild (at least
> in Composer packages) are currently implemented as public static functions,
> and in my opinion, this is starting to sound less like a stop-gap and more
> like a simple solution to a problem we've been solving with a stop-gap for,
> oh, 10 years or so...


Again, if you choose to use static methods instead of functions, why do you
need this special syntax for calling them then?

Regards, Niklas

---

## #97974 — Rasmus Schultz — 2017-01-26T20:23:51+00:00

URL: https://externals.io/message/97888#97974 · In reply to: #97972

> if you choose to use static methods instead of functions

It's not a choice - functions are practically useless in a Composer
context, and most everything PHP is now Composer packages.

> why do you need this special syntax for calling them then?

Yeah, but the same logic applies to namespaces and classes:

If you choose to use namespaces, why do you need aliases for classes?

Strictly speaking, you don't - but it would be really ugly and
inconvenient. Forcing you to qualify a namespace or the parent class of a
function repeatedly is just noise, same as qualifying the namespace before
every class or interface-reference.

Agreed, it has no functional value, but neither does namespace-aliasing.

Both have a considerable organizational benefit though: the ability to list
all your class, interface and function imports at the top of a file.

To me, that's valuable.

Either way, guys, here's a preliminary RFC:

https://wiki.php.net/rfc/use-static-function

While trying to describe this, I have to say, this doesn't appear to be the
slam-dunk it seemed to be - you can read the details on that page, but
given the two alternative approaches described on this page, it seems this
feature is likely to create just as many problems and WTF as the
auto-loading RFC.

I'm afraid one isn't much better or worse than the other in that sense
really...

Oh well :-/




> > […]
>
>
> Again, if you choose to use static methods instead of functions, why do
> you need this special syntax for calling them then?
>
> Regards, Niklas

---

## #97977 — Walter Parker — 2017-01-26T21:37:00+00:00

URL: https://externals.io/message/97888#97977 · In reply to: #97974

> > […]
>
> It's not a choice - functions are practically useless in a Composer
> context, and most everything PHP is now Composer packages.
>
> Why are functions useless when using Composer? Is it because functions
can't be autoloaded?
Is this about getting functions to load without having to stick them in
classes that can be autoloaded?



> > […]
>
> Yeah, but the same logic applies to namespaces and classes:
>
> If you choose to use namespaces, why do you need aliases for classes?
>
> Strictly speaking, you don't - but it would be really ugly and
> inconvenient. Forcing you to qualify a namespace or the parent class of a
> function repeatedly is just noise, same as qualifying the namespace before
> every class or interface-reference.
>
> Agreed, it has no functional value, but neither does namespace-aliasing.
>
> Both have a considerable organizational benefit though: the ability to list
> all your class, interface and function imports at the top of a file.
>
> To me, that's valuable.
>
> Either way, guys, here's a preliminary RFC:
>
> https://wiki.php.net/rfc/use-static-function
>
> While trying to describe this, I have to say, this doesn't appear to be the
> slam-dunk it seemed to be - you can read the details on that page, but
> given the two alternative approaches described on this page, it seems this
> feature is likely to create just as many problems and WTF as the
> auto-loading RFC.
>
> I'm afraid one isn't much better or worse than the other in that sense
> really...
>
> Oh well :-/
>
>
> 
>
> > […]
> with
> > […]
> more
> > […]
>



-- 
The greatest dangers to liberty lurk in insidious encroachment by men of
zeal, well-meaning but without understanding.   -- Justice Louis D. Brandeis

---

## #97978 — Rowan Collins — 2017-01-26T22:06:01+00:00

URL: https://externals.io/message/97888#97978 · In reply to: #97977

> Why are functions useless when using Composer? Is it because functions
> can't be autoloaded?
> Is this about getting functions to load without having to stick them in
> classes that can be autoloaded?

Yes, and yes. The subject line of this thread is an allusion to a 
conversation that resurfaces every now and then but always hits one 
roadblock or another.

In short: the majority of PHP applications and frameworks are based 
around autoloading rather than long lists of explicit dependencies; 
functions can be inside a namespace; but such a function must be 
explicitly defined before use.

Regards,

-- 
Rowan Collins
[IMSoP]

---

## #97979 — Rowan Collins — 2017-01-26T22:10:10+00:00

URL: https://externals.io/message/97888#97979 · In reply to: #97974

> Either way, guys, here's a preliminary RFC:
>
> https://wiki.php.net/rfc/use-static-function

Just to pick up on one thing you mention on there, declaring static 
classes. This has been discussed before, and an RFC went to a vote a 
couple of years ago and failed: 
https://wiki.php.net/rfc/abstract_final_class

Part of the reasoning there was that people should be using namespaced 
functions instead - although that just leads us back to the autoloading 
debate...

Regards,

-- 
Rowan Collins
[IMSoP]

---

## #97987 — Nikita Nefedov — 2017-01-27T14:52:22+00:00

URL: https://externals.io/message/97888#97987 · In reply to: #97888

On Fri, 20 Jan 2017 10:04:44 +0300, Rasmus Schultz <rasmus@mindplay.dk>  
wrote:

> Just a quick thought.
>
> Since the autoloading functions proposal is stalled, how about allowing  
> for
> import of static functions instead?
>
>     use function Foo::bar;
>
>     bar(); // calls Foo::bar()
>
> There are two benefits to this approach:
>
> 1. There is immediate support for autoloading without any need for  
> adoption
> or support in existing autoloaders.
>
> 2. Pseudo-namespaces (abstract classes with stateless static functions)  
> are
> already widely practiced in PHP - a lot of existing code would be  
> supported
> as is.
>
> The syntax when calling functions would be the same.
>
> If we had function autoloading, we would likely collect related functions
> in a file anyway - putting them in a class instead gives more less the  
> same
> exact result.
>
> The only drawback I can see, is the inability to import a whole set of
> functions with one statement - but being explicit about external imports  
> is
> widely considered best practice for classes and interfaces, so why not  
> for
> functions. Yeah, it's a bit inconvenient, but at least we can move ahead
> and leverage existing code without changes or BC breaks. It's not all  
> bad.
> It's better than nothing perhaps? :-)
>
> Thoughts?

Maybe we might think about modules this time?
Lots of languages use this approach and they seem to be pretty happy
with it.

Here's how it could look like, very abstractly. I don't really see
any big issues with the way how to implement it either.

https://gist.github.com/nikita2206/2e4ab1b314e840f93ed75a0b88266d35
