Re: Closures in PHP
| From: | Nathan Nobbe | Date: | Tue, 15 Jan 2008 12:31:22 +0000 |
| Subject: | Re: Closures in PHP | ||
| References: | 1 2 3 4 5 6 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-267282@lists.php.net to get a copy of this message | ||
On Jan 15, 2008 6:51 AM, Jochem Maas <jochem@iamjochem.com> wrote:
> Nathan Nobbe schreef:
> > when it comes to create_function(), id say its just as painful as
> building
> > functions with html or writing queries by hand. namely, its prone to a
> lot
> > of string escaping which produces awful hard to read code. i mean, the
> > kind of code you write yourself and then look at a week later and say
> > 'what a mess'...
>
> agreed - in fact I think I have resorted to create_function only once,
> generally
> when I 'need' it I just resort to writing a std. function that is defined
> in
> or around the code that uses it (as opposed to defining the function in a
> suitable
> functions-only include file) - and give it some oddball name that will
> never
> cause name collisions (e.g. A2mkITdoFooBarSWmagicLanternStuff1timeBla() -
> completely
> unreadable ofcourse but for a throw away used 5 lines up or down it will
> do :-)
>
> > anyway, it occurs to me that the closest thing php has to functional
> > languages,
> > thats readily usable is the variable function mechanism
> > http://www.php.net/manual/en/functions.variable-functions.phpÏôêºCp¨MÜ
> > ^”ð
> > theres been discussion about it on the list in the past, though often it
> is
> > spoken of as a ghost feature. its quite nice.
> > as an example, suppose you have a string
> > $blah = 'myFunc';
> > then if myFunc is defined as a function, it can be invoked per
> > $blah(/* params */);
> >
> > it creates the ability to do all sorts of powerful things, such as
> > delegation
> > whereby switch statements can be eliminated, callbacks, whereby a formal
> > parameter could be a string that refers to a method name, and they work
> > on object references as well. so you can get away w/
> > $this->$dynamicFuncName(/* params*/);
>
> there is a more generic form of callback .. as used by call_user_func*()
> which, if used in conjunction with is_callable() can be a very neat way of
> doing something that resembles meta-programming (okay I'm stretching the
> boat here)
>
> at the very least it allows you a clean and tidy way of introducing
> functionality
> into your code that can be run automatically regardless and without
> breakage,
> in situations where you don't know at run time if the something will exist
> (e.g. some optional CMS module) - following is a silly, contrived example
> to
> give some idea of what can be done:
>
> class foo {
> private $handlers = array();
> static function setHandler($cb) {
> if ($cb && is_callable($cb)/* && !in_array($cb,
> self::$handlers) */)
> self::$handlers[] = $cb;
> }
>
> static function doStuff() {
> foreach(self::$handlers as $cb)
> call_user_func($cb);
> }
> }
>
> class bar {
> function __construct() {
> foo:setHandler( array($this, 'magic') );
> }
>
> function magic() {
> /* er? */
> }
> }
>
> and if you add interfaces and a bit of reflection into the game you can
> get real funky ;-)
>
when i said a function would have to be loaded into the interpreter to avoid
a runtime error
upon invocation, i didnt mention that its best to programatically verify it
can be called before
letting the runtime error occur (of course you can let that happen if you
prefer :)), to avoid it.
anywho, i prefer the variable function construct more than call_user_func(),
simply
because it feels a bit more natural to me, but semantically, they are the
same, they just have
a different syntax is all. i suppose call_user_func() is a bit more clear
and might help some
people when drifting through the code of others.
cool contrived example, btw ;)
-nathan