__autoloading and functions

php.internals

Terje Slettebø

19 years ago
Hi all. I don't know if this has been discussed before (I've not found it from doing a search), but if it has, please provide me with a link to the discussion. __autoload() is very convenient, but it has one problem: While classes defined in the __autoload() function (via an include) are accessible globally, any functions being included are not accessible outside the __autoload() function, making them completely inaccessible to the rest of the system. This means that if you have a file containing a class, as well as one or more associated functions, you won't be able to use the functions, if the file containing the class and functions is loaded using autoloading... I've not found a workaround for this (except reintroducing include_once/require_once, which defeats the whole purpose of autoloading...), are others also experiencing problems with this, and if not, do you a) not use any functions, or b) manage some other way? Has there been considerations for solving this in some way? Example: --- email_address.php --- class EmailAddress { public function __construct($address) { ... } // Check if string contains a valid email address .... private $address; } function email_address($address) { return new EmailAddress($address); } --------------------------------- You may then use this like: $address=email_address(<some string expression>); to make the conversion to EmailAddress less "obtrusive" (simulating implicit conversion to user-defined type). However, this doesn't work with autoloading, so you have to either manually include the above file, or use "new" directly: $address=new EmailAddress(<some string expression>); In other words, this function is not a candidate for making it a method. The problem in this particular example would go away if there was a way to implicitly convert from fundamental types to user-defined types, but that's another discussion... Regards, Terje

Hannes Magnusson

19 years ago
Hello Terje What are you talking about? --class.php-- <?php class foo { } function bar() { print "Hello World\n"; } --foo.php-- <?php function __autoload($class) { include "class.php"; } new foo(); bar(); print "hello world";... -Hannes On 9/10/06, Terje Slettebø <tslettebo@broadpark.no> wrote:

Hannes Magnusson

19 years ago
On 9/10/06, Hannes Magnusson <hannes.magnusson@gmail.com> wrote:
> Hello Terje > > What are you talking about? > --class.php-- > <?php > class foo { > } > > function bar() { > print "Hello World\n"; > } > > --foo.php-- > <?php > function __autoload($class) { > include "class.php"; > } > > new foo(); > bar(); > > print "hello world";...
Gah. I meant to say "Prints out 'hello world'"

Terje Slettebø

19 years ago
Hi Hannes. Ok, so I was wrong about the cause of the "symptom", good - so this is instead another problem: No autoloading of functions... I tried a similar example, where you switch the order of "new foo()" and "bar()" around, and it fails, as it doesn't find the definition of bar(), since class.php hasn't been included at this point... Ok, new question: Autoloading of functions... Has it been considered? Any fundamental problems with it? (Again, except for others requesting the same, I've not found anything else about it, so pointers to any previous discussion of this would be appreciated) Remember that in my example, I called a "factory function" to get an instance of the class, and as you show, it's possible to get that - _after_ you've instantiated the class some other way (or have it call __autoload() in some way), but in the first call to that function, you typically haven't instantiated the class, before... Regards, Terje ----- Original Message ----- From: "Hannes Magnusson" <hannes.magnusson@gmail.com> To: "Terje Slettebø" <tslettebo@broadpark.no> Cc: <internals@lists.php.net> Sent: Sunday, September 10, 2006 4:44 PM Subject: Re: __autoloading and functions Hello Terje What are you talking about? --class.php-- <?php class foo { } function bar() { print "Hello World\n"; } --foo.php-- <?php function __autoload($class) { include "class.php"; } new foo(); bar(); print "hello world";... -Hannes On 9/10/06, Terje Slettebø <tslettebo@broadpark.no> wrote:
> Hi all. > > I don't know if this has been discussed before (I've not found it from
doing
> a search), but if it has, please provide me with a link to the discussion. > > __autoload() is very convenient, but it has one problem: While classes > defined in the __autoload() function (via an include) are accessible > globally, any functions being included are not accessible outside the > __autoload() function, making them completely inaccessible to the rest of > the system. This means that if you have a file containing a class, as well > as one or more associated functions, you won't be able to use the
functions,
> if the file containing the class and functions is loaded using > autoloading... > > I've not found a workaround for this (except reintroducing > include_once/require_once, which defeats the whole purpose of > autoloading...), are others also experiencing problems with this, and if > not, do you a) not use any functions, or b) manage some other way? > > Has there been considerations for solving this in some way? > > Example: > > --- email_address.php --- > > class EmailAddress > { > public function __construct($address) { ... } // Check if string
contains
> a valid email address > .... > private $address; > } > > function email_address($address) > { > return new EmailAddress($address); > } > > --------------------------------- > > You may then use this like: > > $address=email_address(<some string expression>); > > to make the conversion to EmailAddress less "obtrusive" (simulating
implicit
> conversion to user-defined type). > > However, this doesn't work with autoloading, so you have to either
manually
> include the above file, or use "new" directly: > > $address=new EmailAddress(<some string expression>); > > In other words, this function is not a candidate for making it a method. > > The problem in this particular example would go away if there was a way to > implicitly convert from fundamental types to user-defined types, but
that's

Marcus Börger

19 years ago
Hello Terje, it hasbeendiscussed and the conclusion is that it isfar too much of a slowdown for every function call and thus we are not going to implement it. The speed reasoning put aside we also found that procedural techniques should not mix too much with the object oriented features. bes regards marcus Sunday, September 10, 2006, 5:30:54 PM, you wrote:

Terje Slettebø

19 years ago
Hi Marcus. Thanks for the replies, both of you. I've solved this particular problem by having all these little functions in a file that gets included for all files that need it.
> The speed reasoning put aside we also found that procedural techniques > should not mix too much with the object oriented features.
Could I ask why not? I can give my own thoughts to the opposite: I (and much of the programming community, it seems) have come to that it's a perfectly reasonable way to program, where you use the best abstractions for the task (ironically, PHP is better than Java in this respect, as Java doesn't support free functions). This goes under the name of multi-paradigm design (http://www.artima.com/weblogs/viewpost.jsp?thread=167119), and aims at avoiding the myopic view people tend to get when only one "paradigm" is available to them (or familiar to them). In fact, combining "paradigms" is what gives MPD much of its power, as it enables you to do things that no single "paradigm", by itself, can do. Trying to shoehorn everything into _one_ "paradigm" (whether it's procedural programming, OO, functional programming, or whether) may lead to some very contorted designs... To paraphrase a well-known phrase: If all you know is OO, everything will look like an object (whether or not it makes any sense). However, I guess this discussion may not belong on internals... However, to use this concrete example, could you tell me why e.g.: $value=Something::something(<something else>); // A related issue: Is this even OO? We're not operating on an object... would be better than: $value=something(<something else>); The latter is less to type, which is much of the reason for it in the first place, as well as it looking like a C++-style cast, which is how it behaves. The first version really isn't a better alternative to "new Something(<something else>)". Regards, Terje P.S: As an aside: Why is everybody (?) replying to both the list _and_ the poster? If you post, isn't it safe to assume you're actually on the list, or am I missing something? ----- Original Message ----- From: "Marcus Boerger" <helly@php.net> To: "Terje Slettebø" <tslettebo@broadpark.no> Cc: "Hannes Magnusson" <hannes.magnusson@gmail.com>; <internals@lists.php.net> Sent: Sunday, September 10, 2006 5:35 PM Subject: Re: [PHP-DEV] Re: __autoloading and functions
> Hello Terje, > > it hasbeendiscussed and the conclusion is that it isfar too much of a > slowdown for every function call and thus we are not going to implement > it. The speed reasoning put aside we also found that procedural techniques > should not mix too much with the object oriented features. > > bes regards > marcus > > Sunday, September 10, 2006, 5:30:54 PM, you wrote: > > > Hi Hannes. > > > Ok, so I was wrong about the cause of the "symptom", good - so this is > > instead another problem: No autoloading of functions... I tried a
similar
> > example, where you switch the order of "new foo()" and "bar()" around,
and
> > it fails, as it doesn't find the definition of bar(), since class.php
hasn't
> > been included at this point... > > > Ok, new question: Autoloading of functions... Has it been considered?
Any
> > fundamental problems with it? (Again, except for others requesting the
same,
> > I've not found anything else about it, so pointers to any previous > > discussion of this would be appreciated) > > > Remember that in my example, I called a "factory function" to get an > > instance of the class, and as you show, it's possible to get that -
_after_
> > you've instantiated the class some other way (or have it call
__autoload()
> > in some way), but in the first call to that function, you typically
haven't
> > instantiated the class, before... > > > Regards, > > > Terje > > > ----- Original Message ----- > > From: "Hannes Magnusson" <hannes.magnusson@gmail.com> > > To: "Terje Slettebø" <tslettebo@broadpark.no> > > Cc: <internals@lists.php.net> > > Sent: Sunday, September 10, 2006 4:44 PM > > Subject: Re: __autoloading and functions > > > > Hello Terje > > > What are you talking about? > > --class.php-- > > <?php > > class foo { > > } > > > function bar() { > > print "Hello World\n"; > > } > > > --foo.php-- > > <?php > > function __autoload($class) { > > include "class.php"; > > } > > > new foo(); > > bar(); > > > print "hello world";... > > > -Hannes > > > On 9/10/06, Terje Slettebø <tslettebo@broadpark.no> wrote: > >> Hi all. > >> > >> I don't know if this has been discussed before (I've not found it from > > doing > >> a search), but if it has, please provide me with a link to the
discussion.
> >> > >> __autoload() is very convenient, but it has one problem: While classes > >> defined in the __autoload() function (via an include) are accessible > >> globally, any functions being included are not accessible outside the > >> __autoload() function, making them completely inaccessible to the rest
of
> >> the system. This means that if you have a file containing a class, as
well
> >> as one or more associated functions, you won't be able to use the > > functions, > >> if the file containing the class and functions is loaded using > >> autoloading... > >> > >> I've not found a workaround for this (except reintroducing > >> include_once/require_once, which defeats the whole purpose of > >> autoloading...), are others also experiencing problems with this, and
if
> >> not, do you a) not use any functions, or b) manage some other way? > >> > >> Has there been considerations for solving this in some way? > >> > >> Example: > >> > >> --- email_address.php --- > >> > >> class EmailAddress > >> { > >> public function __construct($address) { ... } // Check if string > > contains > >> a valid email address > >> .... > >> private $address; > >> } > >> > >> function email_address($address) > >> { > >> return new EmailAddress($address); > >> } > >> > >> --------------------------------- > >> > >> You may then use this like: > >> > >> $address=email_address(<some string expression>); > >> > >> to make the conversion to EmailAddress less "obtrusive" (simulating > > implicit > >> conversion to user-defined type). > >> > >> However, this doesn't work with autoloading, so you have to either > > manually > >> include the above file, or use "new" directly: > >> > >> $address=new EmailAddress(<some string expression>); > >> > >> In other words, this function is not a candidate for making it a
method.
> >> > >> The problem in this particular example would go away if there was a way
to

Pierre Joye

19 years ago
Hello,
> P.S: As an aside: Why is everybody (?) replying to both the list _and_ the > poster? If you post, isn't it safe to assume you're actually on the list, or > am I missing something?
It is a common usage here. Some uses nntp, other mails (and filters, etc..). It is also nice to do not start a new thread for no obvious reason but having another topic, it makes a mess out of the archives and is harder to follow. --Pierre

Terje Slettebø

19 years ago
Hi Pierre.
> > P.S: As an aside: Why is everybody (?) replying to both the list _and_
the
> > poster? If you post, isn't it safe to assume you're actually on the
list, or
> > am I missing something? > > It is a common usage here. Some uses nntp, other mails (and filters,
etc..). Ok. It's just that it's very unusual for mailing lists (at least the ones I have experience with), but whatever.
> It is also nice to do not start a new thread for no obvious reason but > having another topic, it makes a mess out of the archives and is > harder to follow.
I'm afraid I didn't understand your point. When you say "start a thread", do you mean changing the subject line (as I did)? It's my understanding that people in general prefer that you change the subject line, if the topic changes, as it otherwise makes it much harder to follow the discussion... (and you may have to wade through a lot of postings having nothing to do with the subject line, or miss an interesting discussion, for the same reason). But then again, maybe also these things work differently "here", than other places... :) Regards, Terje

Derick Rethans

19 years ago
On Sun, 10 Sep 2006, Terje Slettebø wrote:
> > > P.S: As an aside: Why is everybody (?) replying to both the list > > > _and_ the poster? If you post, isn't it safe to assume you're > > > actually on the list, or am I missing something? > > > > It is a common usage here. Some uses nntp, other mails (and filters, > etc..). > > Ok. It's just that it's very unusual for mailing lists (at least the > ones I have experience with), but whatever.
The following URL explains why it is a bad idea to mangle the reply-to header (like some other lists do): http://www.unicom.com/pw/reply-to-harmful.html
> > It is also nice to do not start a new thread for no obvious reason but > > having another topic, it makes a mess out of the archives and is > > harder to follow. > > I'm afraid I didn't understand your point. When you say "start a thread", do > you mean changing the subject line (as I did)? It's my understanding that > people in general prefer that you change the subject line, if the topic > changes, as it otherwise makes it much harder to follow the discussion... > (and you may have to wade through a lot of postings having nothing to do > with the subject line, or miss an interesting discussion, for the same > reason).
Yup, but you should use "New Mail" and not "Reply-To" in that case as now the new mail appears in the same thread as the old subject. regards, Derick
-- Derick Rethans http://derickrethans.nl | http://ez.no | http://xdebug.org

Rasmus Lerdorf

19 years ago
Terje Slettebø wrote:
> P.S: As an aside: Why is everybody (?) replying to both the list _and_ the > poster? If you post, isn't it safe to assume you're actually on the list, or > am I missing something?
Many people aren't actually subscribed, the list can be slow at times, and it is nice to have replies to your questions emailed directly to you so you can have your email client pick them out easily for you. Most of us also have something like this procmail rule in place: :0 Whc: msgid.lock | formail -D 16384 msgid.cache :0 a: duplicates So we don't actually see 2 copies. We only see the first one that arrives. -Rasmus

dAniel hAhler

19 years ago
Marcus Boerger wrote:
> it hasbeendiscussed and the conclusion is that it isfar too much of a > slowdown for every function call and thus we are not going to implement > it.
Maybe a dump question, but wouldn't it get considered only, AFTER PHP has found that the function does not exist? So, it shouldn't be a slowdown at all. On the other hand I don't know the internals of PHP very much.
> The speed reasoning put aside we also found that procedural techniques > should not mix too much with the object oriented features.
This may be a reason, but I for one would not think that this is "dirty".

Richard Quadling

19 years ago
On 10/09/06, dAniel hAhler <php@thequod.de> wrote:
> Marcus Boerger wrote: > > > it hasbeendiscussed and the conclusion is that it isfar too much of a > > slowdown for every function call and thus we are not going to implement > > it. > > Maybe a dump question, but wouldn't it get considered only, AFTER PHP has > found that the function does not exist? > > So, it shouldn't be a slowdown at all. > > On the other hand I don't know the internals of PHP very much. > > > > The speed reasoning put aside we also found that procedural techniques > > should not mix too much with the object oriented features. > > This may be a reason, but I for one would not think that this is "dirty". > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
One way in useerland to solve this is to use an error handler to identify non existant function calls and then use an appropriate mechanism to find them. The only slowdown would be when an error occurred (but acceptable). If the functions where kept in files of their own name, then this would be the end of function libraries and a LOT of additional files. This could promote refactoring to take groups of related functions and convert them to a class to allow for autoloading to work.
-- ----- Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&amp;r=213474731 "Standing on the shoulders of some very clever giants!"

Michael Walter

19 years ago
On 9/11/06, Richard Quadling <rquadling@googlemail.com> wrote:
> One way in useerland to solve this is to use an error handler to > identify non existant function calls and then use an appropriate > mechanism to find them.
You can't catch fatal errors. Regards, Michael

Stanislav Malyshev

19 years ago
>> Maybe a dump question, but wouldn't it get considered only, AFTER PHP has >> found that the function does not exist?
Technically, this can be done - i.e. engine can be patched so that instead of throwing an error or refusing the call it would call appropriate function which would allow for autoloading. However, I think autoloading functions if conceptually wrong. One rarely keeps functions individually separated in different files (while this is routinely happening - and is recommended - for classes). So, if you want to autoload functions you would either have to build complex tables of where each function lives or organize them in some well-defined modules. Such modules are called "classes" in OO-speak, so if you have a group of functions that are united by purpose and you want to autoload - why not to make a class out of them? And if there's just an assortment of unrelated functions - it would probably promote very ugly code if we allow to autoload them individually.

Terje Slettebø

19 years ago
> >> Maybe a dump question, but wouldn't it get considered only, AFTER PHP
has
> >> found that the function does not exist? > > Technically, this can be done - i.e. engine can be patched so that > instead of throwing an error or refusing the call it would call > appropriate function which would allow for autoloading. > > However, I think autoloading functions if conceptually wrong. One rarely > keeps functions individually separated in different files (while this is > routinely happening - and is recommended - for classes). So, if you want > to autoload functions you would either have to build complex tables of > where each function lives or organize them in some well-defined modules. > Such modules are called "classes" in OO-speak
Or "namespaces"... Or just plain "modules". Classes is not the only way to group things, and may not be the best (namespaces can typically be re-opened, so functions and classes belonging to a namespace can span several files, instead of everything having to be in _one_ file).
>, so if you have a group of > functions that are united by purpose and you want to autoload - why not > to make a class out of them?
Why? Besides the above, because you may want to be able to call a function like: f(); and not: SomeClassToWrapItAll::f(); ... Please, people: The availability of free (non-member) functions in PHP (as in C/C++) is one advantage it has over Java, where everything _has_ to be a class. So in Java, instead of being able to write "sqrt(<number>)", you have to write "Math::sqrt(<number>)". Always. And one small plea: If namespaces are added to PHP, please don't add something like C++'s "argument-dependent lookup": It has caused no end of problems in that camp. :) Regards, Terje

Stanislav Malyshev

19 years ago
> Or "namespaces"... Or just plain "modules". Classes is not the only way to > group things, and may not be the best (namespaces can typically be >
Oh, of course it's not the only way. It's the only way native to PHP though.
> re-opened, so functions and classes belonging to a namespace can span > several files, instead of everything having to be in _one_ file). >
Thus, how do you suppose autoloading function would know which file to load? We are back to the "complex ugly logic" argument.
> Why? Besides the above, because you may want to be able to call a function > like: > > f(); > > and not: > > SomeClassToWrapItAll::f(); >
You may call the class x if you like one-letter names :) Besides that, saving keystrokes was never a top priority for PHP (see how elaborate function names standard modules have). Keystrokes are cheap, clarity of the code isn't.
> class. So in Java, instead of being able to write "sqrt(<number>)", you have > to write "Math::sqrt(<number>)". Always. >
Frankly, I don't really see it as advantage or disadvantage, it's just another way to say the same. Java, for good and for bad, is much more organized and bureaucratic language than PHP. In PHP nobody makes you to use classes if you don't like them, I am just saying trying to make functions behave like they belong to class or module without either saying "class" or "module" (i.e. include) may not be the best idea to support.
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/

Terje Slettebø

19 years ago
> > Or "namespaces"... Or just plain "modules". Classes is not the only way
to
> > group things, and may not be the best (namespaces can typically be > > > Oh, of course it's not the only way. It's the only way native to PHP
though. Yes.
> > re-opened, so functions and classes belonging to a namespace can span > > several files, instead of everything having to be in _one_ file). > > > Thus, how do you suppose autoloading function would know which file to > load? We are back to the "complex ugly logic" argument.
That's not something I've thought through: I just wanted to point out that classes are not the only way to group things. I've quite recently started to read the postings, here, but I intend to read up on the relevant discussions in previous postings to the list, to know what has been discussed, and what has come from it.
> > Why? Besides the above, because you may want to be able to call a
function
> > like: > > > > f(); > > > > and not: > > > > SomeClassToWrapItAll::f(); > > > You may call the class x if you like one-letter names :)
No thanks, I prefer readability. :)
> Besides that, saving keystrokes was never a top priority for PHP
Uah...
> (see how elaborate function names standard modules have).
Yes... "Wonderful", isn't it? :) Sorry, like I said, I'll read up on previous discussion of things like namespaces, before jumping into a discussion about them. Still, just one observation...: Verbosity rarely lead to clarity, it's rather the other way around.
> Keystrokes are cheap, clarity of the code isn't.
Clarity is very important, but always spelling things out in full may lead to less clear code. However, I'd think this is a discussion that is more appropriate at php-general...
> I am just saying trying to make > functions behave like they belong to class or module without either > saying "class" or "module" (i.e. include) may not be the best idea to > support.
I'm not sure I follow you... In for example Java, you have packages (modules), and you may either use the full name of a class all of the time, such as "java.lang.Math::sqrt(...)" or "Math::sqrt(...)" (or even "sqrt(...)", in a language supporting free functions). You seem to argue for the first one, for "clarity"... In either of the above cases, you specify where a function belongs, both where it's defined, and where it's used (either through full qualification, or a shorter one, using "import"). I'm not arguing for a function to "magically" become a part of a class/module/whatever, if you thought so (there's way too much "magic" in PHP as it is, and the separation between what "implementors" can do, and what "userland" is allowed to, is not a separation I like, either, but that's another discussion). Regards, Terje

Michael Walter

19 years ago
On 9/11/06, Terje Slettebø <tslettebo@broadpark.no> wrote:
> Please, people: The availability of free (non-member) functions in PHP (as > in C/C++) is one advantage it has over Java, where everything _has_ to be a > class. So in Java, instead of being able to write "sqrt(<number>)", you have > to write "Math::sqrt(<number>)". Always.
Actually, Java recently added static import to deal with that very annoyance.... ;) Regards, Michael

Terje Slettebø

19 years ago
>On 9/11/06, Terje Slettebø <tslettebo@broadpark.no> wrote: >> Please, people: The availability of free (non-member) functions in PHP
(as
>> in C/C++) is one advantage it has over Java, where everything _has_ to be
a
>> class. So in Java, instead of being able to write "sqrt(<number>)", you
have
>> to write "Math::sqrt(<number>)". Always.
>Actually, Java recently added static import to deal with that very >annoyance.... ;)
Right. Well, to me, having to wrap everything in a class, just because you don't have free functions, seems like more of a workaround than anything else, and the static import a "kludge" to make that less inconvenient (conceptually, it doesn't make a lot of sense to me to "import" some class's static members into a context...). Besides, it forces you to define everything in _one_ file (unless _that_ has been changed, as well). I'm reminded of that, after having learned Java at college, and taking up C++ again, after it, I had to "deprogram" myself of "Javaisms": I tended to use a class for everything, even if it made my design more complex and tighter coupled than necessary. For example, if I needed some functions that didn't naturally belong in a class (such as various "utility functions"), I'd wrap them as static members in a class called "Utility". When reading up on C++, again, I realised that this was absolutely not necessary: You could simply define them as free functions in a namespace called "utility"... That way, they may be called unqualified (if "imported" with "using"), and may span several files. Regards, Terje