PATCH: anonymous functions in PHP

php.internals

Wez Furlong

19 years ago
We've been daydreaming about the ability to do something like this in PHP: $data = array("zoo", "orange", "car", "lemon", "apple"); usort($data, function($a, $b) { return strcmp($a, $b); }); var_dump($data); # data is sorted alphabetically In the past, people have been told to use the travesty that is create_function() to emulate this kind of behavior, well, it turns out to be a minor patch to the parser to pull that into the core. You can find my prototype patch at http://pastebin.ca/400871 (against PHP_5_2) The way it works is by making the expression: function() {} evaluate to the (generated) name of the anonymous function. $foo = function() {}; sets $foo to a string like "__zend_anon_1", which can then be passed around as a callback name, just like the way that create_function() works, except that you don't need to use crazy quoting to declare any kind of moderately complex function. There's one minor flaw in my implementation for ZTS enabled systems (just need to move the anon function counter into CG() to solve that. So, the question is, do we want this in PHP? --Wez.

Jan Lehnardt

19 years ago
On Mon 19 Mar 2007, at 19 Mar 00:41, Wez Furlong wrote:
> So, the question is, do we want this in PHP?
yes, please. Jan
--

Wez Furlong

19 years ago
I found another flaw; when used in a loop it keeps trying to declare the same function over and over. I think this is because the ZEND_DECLARE_FUNCTION opcode is emitted as part of the arg list building op sequence. I'm poking to find an elegant way to fix that. --Wez. On Mar 18, 2007, at 7:41 PM, Wez Furlong wrote:

Jim Wilson

19 years ago
> > So, the question is, do we want this in PHP? > > yes, please.
Anonymous function declaration is one of the things I've always loved in Ruby and JavaScript - I for one would _love to see this_ in php. -- Jim R. Wilson (jimbojw) On 3/18/07, Wez Furlong <wez@omniti.com> wrote:

Wez Furlong

19 years ago
Updated patch at http://pastebin.ca/400952 Not 100% sure if my hack in zend_compile.c is righteous, but it doesn't seem too far wrong. --Wez.

Gwynne

19 years ago
On Mar 18, 2007, at 8:48 PM, Wez Furlong wrote:
> Updated patch at http://pastebin.ca/400952 > Not 100% sure if my hack in zend_compile.c is righteous, but it > doesn't seem too far wrong.
74. + if (!memcmp(opline-
>op2.u.constant.value.str.val, "__zend_anon_", sizeof
("__zend_anon_")-1)) { Pardon my nitpicking, but shouldn't this be: 74. + if (!memcmp(opline-
>op2.u.constant.value.str.val, "__zend_anon_", strlen
("__zend_anon_")-1)) { Also, a strong +1 for this patch, I'd love to see this support in PHP. -- Gwynne, Daughter of the Code "This whole world is an asylum for the incurable."

Wez Furlong

19 years ago
Your nitpicking happens to be wrong ;-) sizeof("string constant") is the "same" as strlen("string constant") +1, but is resolved at compile time, so we use sizeof("string constant")-1 to get a compile time evaluated strlen(). This trick is used throughout the PHP internals. --Wez. On Mar 18, 2007, at 9:27 PM, Gwynne wrote:

Gwynne

19 years ago
On Mar 18, 2007, at 9:30 PM, Wez Furlong wrote:
> Your nitpicking happens to be wrong ;-) > > sizeof("string constant") is the "same" as strlen("string constant") > +1, but is resolved at compile time, so we use sizeof("string > constant")-1 to get a compile time evaluated strlen(). This trick > is used throughout the PHP internals.
Ah. I've never seen it used that way before; I apologize for my ignorance :). In my experience, sizeof() on a character constant would evaluate as sizeof( const char * const ).
> On Mar 18, 2007, at 9:27 PM, Gwynne wrote: >>> Updated patch at http://pastebin.ca/400952 >>> Not 100% sure if my hack in zend_compile.c is righteous, but it >>> doesn't seem too far wrong. >> >> 74. + if (!memcmp(opline- >> >op2.u.constant.value.str.val, "__zend_anon_", sizeof >> ("__zend_anon_")-1)) { >> >> Pardon my nitpicking, but shouldn't this be: >> >> 74. + if (!memcmp(opline- >> >op2.u.constant.value.str.val, "__zend_anon_", strlen >> ("__zend_anon_")-1)) { >> >> Also, a strong +1 for this patch, I'd love to see this support in >> PHP.
-- Gwynne, Daughter of the Code "This whole world is an asylum for the incurable."

Marcus Börger

19 years ago
Hello Gwynne, Monday, March 19, 2007, 3:13:28 AM, you wrote:
> On Mar 18, 2007, at 9:30 PM, Wez Furlong wrote: >> Your nitpicking happens to be wrong ;-) >> >> sizeof("string constant") is the "same" as strlen("string constant") >> +1, but is resolved at compile time, so we use sizeof("string >> constant")-1 to get a compile time evaluated strlen(). This trick >> is used throughout the PHP internals.
> Ah. I've never seen it used that way before; I apologize for my > ignorance :). In my experience, sizeof() on a character constant > would evaluate as sizeof( const char * const ).
Actually it is not a "const char *" here. Instead the language generates a "const char[]" which works asexpected. Best regards, Marcus

Marcus Börger

19 years ago
Hello Wez, interesting solution. Nice work:-) Monday, March 19, 2007, 1:48:31 AM, you wrote:
> Updated patch at http://pastebin.ca/400952 > Not 100% sure if my hack in zend_compile.c is righteous, but it > doesn't seem too far wrong.
> --Wez.
Best regards, Marcus

Jacob Santos

19 years ago
Hey, thanks, I was researching this exact same thing. You make it appear much easier than it is. You've just saved me many months, weeks, and hours trying to figure out how to mess with the internals of the Zend Engine. For that, I am most grateful. Also, I would love to see this in PHP, at the very least it would negate the argument of those who say PHP doesn't support anonymous functions. Jacob Santos

Stanislav Malyshev

19 years ago
> Also, I would love to see this in PHP, at the very least it would negate > the argument of those who say PHP doesn't support anonymous functions.
This argument is false in any case, since create_function exists and this implementation is other way to write create_function :)
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/

Jon Parise

19 years ago
On Sun, Mar 18, 2007 at 08:48:31PM -0400, Wez Furlong wrote:
> Updated patch at http://pastebin.ca/400952
This is interesting. I'm not sure I'll ever use it (I prefer named functions), but it's a purely optional and folks seem to want something like this. One comment on the patch itself: static unsigned int anon_count; I think you should provide an initial value (0?) for this static counter. Also, you should protect against wrap-around (which, while improbably, is possible). Alternatively, you could change the anonymous function naming scheme to something like __zend_anon_FILE_LINE_COLUMN, but that could be an unnecessary waste of string memory.
-- Jon Parise (jon of php.net) :: The PHP Project (http://www.php.net/)

Richard Lynch

19 years ago
On Sun, March 18, 2007 7:30 pm, Wez Furlong wrote:
> I found another flaw; when used in a loop it keeps trying to declare > the same function over and over. I think this is because the > ZEND_DECLARE_FUNCTION opcode is emitted as part of the arg list > building op sequence. > > I'm poking to find an elegant way to fix that.
Would the function body/arglist be allowed to change based on the loop data? [shudder] It's starting to sound like Lisp :-) Though I guess if you need anonymous functions, you probably need them with varying bodies as well.
-- Some people have a "gift" link here. Know what I want? I want you to buy a CD from some starving artist. http://cdbaby.com/browse/from/lynch Yeah, I get a buck. So?

Stanislav Malyshev

19 years ago
> $data = array("zoo", "orange", "car", "lemon", "apple"); > usort($data, function($a, $b) { return strcmp($a, $b); }); > var_dump($data); # data is sorted alphabetically
What happens if you do this: $data = array("zoo", "orange", "car", "lemon", "apple"); $rev = 1; usort($data, function($a, $b) { return $rev?strcmp($a, $b):!strcmp($a, $b); }); var_dump($data); # data is sorted alphabetically This works in Javascript (probably Ruby too), but quite hard to make work in PHP because $rev is in different scope. Moreover, would it mean that this: $f = function($a, $b) { return $rev?strcmp($a, $b):!strcmp($a, $b); } would work too? Keeping right value of $rev?
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/

Wez Furlong

19 years ago
I didn't make it do anything fancy with scoping; it would make the implementation more complicated, and wouldn't fit so well with the way that scoping works in PHP, in that you need to explicitly reference the global scope to "break out" of your function scope. It would be cool if the lexical scope was inherited, but maybe not cool enough to warrant making it work :) --Wez. On Mar 18, 2007, at 10:06 PM, Stanislav Malyshev wrote:

Stanislav Malyshev

19 years ago
> I didn't make it do anything fancy with scoping; it would make the > implementation more complicated, and wouldn't fit so well with the way > that scoping works in PHP, in that you need to explicitly reference the > global scope to "break out" of your function scope. > > It would be cool if the lexical scope was inherited, but maybe not cool > enough to warrant making it work :)
Well, making it work makes this thing closure. Otherwise it's just a nice way to save a couple of keystrokes :) Not to diminish your work, but there's a danger people would think it is closure because it looks like one (i.e., in other languages closures look exactly this way, e.g. Javascript).
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/

Christian Schneider

19 years ago
Stanislav Malyshev wrote:
> Well, making it work makes this thing closure. Otherwise it's just a > nice way to save a couple of keystrokes :) Not to diminish your work, > but there's a danger people would think it is closure because it looks > like one (i.e., in other languages closures look exactly this way, e.g. > Javascript).
Wez' proposal sounds very intriguing. At the same time I wouldn't try to add closures to PHP as while they might be a mighty concept they are also complicated and have a high WTF factor IMHO. When I first started doing more complex things in Javascript I was bitten more than once by closures: Sometimes they did what I expected and sometimes they didn't (e.g. when using 'this'). But I agree that it would be great to being able to pass context to the generated function, preferably not via a global variable. One possible solution would be to generate the function as a method of the current object and expose this so something like usort($data, function($a, $b) { return $this->cmp($a, $b); }); could be used. - Chris

Sean Coates

19 years ago
> Well, making it work makes this thing closure. Otherwise it's just a > nice way to save a couple of keystrokes :) Not to diminish your work, > but there's a danger people would think it is closure because it looks > like one (i.e., in other languages closures look exactly this way, e.g. > Javascript).
I think this is the key to this whole discussion. I doubt PHP will ever be able to fully support JavaScript- and Lisp-style closures. To take Stas' example to another level: function foo() { $bar = function () { echo "bar"; } return $bar; } $bar = foo(); $bar(); // does this work? According to our current current syntax: function foo() { $bar = create_function('', 'echo "bar";'); return $bar; } $bar = foo(); $bar(); // this does work I don't know Lisp very well at all, but in JavaScript, functions are general containers, and this sort of thing works fine, albeit VERY differently. PHP's scoping rules are already completely different from JavaScript's (there's no way to access the parent scope unless it happens to be the global scope). I strongly prefer Wez's syntax for anonymous function declaration. It would help on many levels, from readability to syntax-highlighting, to optimization (maybe...). On optimization, the question becomes "how does Wez's proposal tokenize?" --------Old: T_OPEN_TAG : <?php T_VARIABLE : $bar T_WHITESPACE : = T_WHITESPACE : T_STRING : create_function ( T_CONSTANT_ENCAPSED_STRING : '' , T_WHITESPACE : T_CONSTANT_ENCAPSED_STRING : 'echo "bar";' ) ; --------New: T_OPEN_TAG : <?php T_VARIABLE : $bar T_WHITESPACE : = T_WHITESPACE : T_FUNCTION : function ( ) T_WHITESPACE : { T_WHITESPACE : T_ECHO : echo T_WHITESPACE : T_CONSTANT_ENCAPSED_STRING : "bar" ; T_WHITESPACE : } ; If the answer is "New", then this could be compiled at.. well, compile-time, not at execute time. That could be even more interesting. (sorry for the long post.. most of it's code (-; ) S

Stanislav Malyshev

19 years ago
> If the answer is "New", then this could be compiled at.. well, > compile-time, not at execute time. That could be even more interesting.
If it would create anonymous function compile-time, it would be a big advantage to Wez's patch because then this function could be cached. Thinking about this, maybe it is the reason enough to do this even if it's not real closure.
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/

Sean Coates

19 years ago
> If it would create anonymous function compile-time, it would be a big > advantage to Wez's patch because then this function could be cached. > Thinking about this, maybe it is the reason enough to do this even if > it's not real closure.
On mulling this over a bit more, other than quick one-off callbacks (which would definitely benefit from avoiding compile on every request), one of the key reasons to use create_function() is actually to create dynamic functions: $fancyVer = create_function('', 'return "PHP " . phpversion();'); // could be optimized as: $fancyVer = create_function('', 'return "PHP ' . phpversion() .'";'); (the latter only calls phpversion() at declaration, not each time the lambda runs) Since phpversion() is available globally, this isn't a problem. But what happens if we want to use a variable, instead? $ver = phpversion(); $fancyVer = create_function('', "return 'PHP $ver';"); // this currently works ^ How would this be rewritten, though? $ver = phpversion(); $fancyVer = function () { return "PHP $ver"; }; where would $ver come from? the parent scope? the lambda's local scope? what if it's defined in both places? S

Wez Furlong

19 years ago
I've been thinking about this on and off today too. Something along the lines of the following is more in the PHP spirit: $ver = phpversion(); $fancyVer = function () { lexical $ver; return "PHP $ver"; }; Where "lexical" is a keyword that means "inherit this variable from the current lexical scope". I'm not suggesting that this is a good name for the keyword, it's just something that springs to mind. So, given some way to explicitly reference the scope where the function was "defined", what happens when you call $fancyVer after that scope has gone away: function doSomething() { $ver = phpversion(); return function () { lexical $ver; return "PHP $ver"; }; } $func = doSomething(); $func(); # the doSomething() scope (hash table) doesn't exist any more This could perhaps be solved by taking a reference to $ver when the function is bound, but I don't know enough about the ZE to understand the implications of that; it would probably require a bit more state tracking per zend_function so that we know that we need to do that step during binding. --Wez. On Mar 19, 2007, at 3:25 PM, Sean Coates wrote:

Sean Coates

19 years ago
If we can solve the scoping problem (perhaps via references as you mentioned), then lexical (or another keyword, to be debated endlessly for months, whose name-debate will delay the implementation of this functionality, but I digress...) seems like a good solution to grabbing scope, and fits the "PHP Way", IMO.
> So, given some way to explicitly reference the scope where the function > was "defined", what happens when you call $fancyVer after that scope has > gone away:
This was my next question (-:
> This could perhaps be solved by taking a reference to $ver when the > function is bound, but I don't know enough about the ZE to understand > the implications of that; it would probably require a bit more state > tracking per zend_function so that we know that we need to do that step > during binding.
JavaScript (and I suspect other Lisp-like languages) solves this by making the function an actual closure—the defined function maintains access to the parent scope, even after the parent's hash table (or however it works in JS) would have normally been destroyed. I think the key thing to remember here is that JS is fundamentally different from PHP. Functions are objects in JS, and they always have access to variables from all parent scopes. I don't think PHP can (or should) ever implement this. I also don't know what I'm talking about when it comes to ZE internals, so if I'm way off base, feel free to put me in line (-: (I maintain that JS' wonky (though useful) scoping rules should never be assimilated in PHP.) S

Stanislav Malyshev

19 years ago
> I've been thinking about this on and off today too. > Something along the lines of the following is more in the PHP spirit: > > $ver = phpversion(); > $fancyVer = function () { lexical $ver; return "PHP $ver"; }; > > Where "lexical" is a keyword that means "inherit this variable from the > current lexical scope". I'm not suggesting that this is a good name for > the keyword, it's just something that springs to mind.
How this is going to work? Variables are not interpreted by the compiler now...
> So, given some way to explicitly reference the scope where the function > was "defined", what happens when you call $fancyVer after that scope has > gone away:
Exactly! That's why it is hard to do closures in PHP :)
> This could perhaps be solved by taking a reference to $ver when the > function is bound, but I don't know enough about the ZE to understand > the implications of that; it would probably require a bit more state
$ver would not even exist when we compile it - $ver appears in run-time and we want function to be created in compile-time!
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/

Robert Cummings

19 years ago
On Mon, 2007-03-19 at 13:15 -0700, Stanislav Malyshev wrote:
> > I've been thinking about this on and off today too. > > Something along the lines of the following is more in the PHP spirit: > > > > $ver = phpversion(); > > $fancyVer = function () { lexical $ver; return "PHP $ver"; }; > > > > Where "lexical" is a keyword that means "inherit this variable from the > > current lexical scope". I'm not suggesting that this is a good name for > > the keyword, it's just something that springs to mind. > > How this is going to work? Variables are not interpreted by the compiler > now... > > > So, given some way to explicitly reference the scope where the function > > was "defined", what happens when you call $fancyVer after that scope has > > gone away: > > Exactly! That's why it is hard to do closures in PHP :)
What about just having a function that allows retrieving variables from the parent scope? mixed seek_var( $name [, $levels=1, [ $startLevel=0 ] ] ) Returns the the value of the variable with name $name in the current of parent lexical scopes. By default the seek will only search for the variable in the current and immediate parent scopes but this can be tailored to meet any particular need including searching to the top by setting $levels to -1. Additionally by setting $startLevel greater than 0, the search can be confined to scopes outside of the current lexical scope. If the request variable is not found then E_NOTICE is generated and null is returned. Cheers, Rob.
-- .------------------------------------------------------------. | InterJinn Application Framework - http://www.interjinn.com | :------------------------------------------------------------: | An application and templating framework for PHP. Boasting | | a powerful, scalable system for accessing system services | | such as forms, properties, sessions, and caches. InterJinn | | also provides an extremely flexible architecture for | | creating re-usable components quickly and easily. | `------------------------------------------------------------'

Wez Furlong

19 years ago
On Mar 19, 2007, at 4:15 PM, Stanislav Malyshev wrote:
> How this is going to work? Variables are not interpreted by the > compiler now... >
Well, the compiler would make a list of variables names to import and store those in the zend_function structure. Then at the time the function is bound (in response to a DECLARE_FUNCTION opcode), the variable reference could be fixed up in the "same" way that global is handled. --Wez.

Richard Lynch

19 years ago
On Mon, March 19, 2007 2:33 pm, Wez Furlong wrote:
> I've been thinking about this on and off today too. > Something along the lines of the following is more in the PHP spirit: > > $ver = phpversion(); > $fancyVer = function () { lexical $ver; return "PHP $ver"; }; > > Where "lexical" is a keyword that means "inherit this variable from > the current lexical scope". I'm not suggesting that this is a good > name for the keyword, it's just something that springs to mind.
I believe "Environment" is what it was called back in CLOS when we schlepped it around as an extra extra argument to functions that needed data from outside function scope...
> So, given some way to explicitly reference the scope where the > function was "defined", what happens when you call $fancyVer after > that scope has gone away: > > function doSomething() { > $ver = phpversion(); > return function () { lexical $ver; return "PHP $ver"; }; > } > $func = doSomething(); > $func(); # the doSomething() scope (hash table) doesn't exist any more > > This could perhaps be solved by taking a reference to $ver when the > function is bound, but I don't know enough about the ZE to understand > the implications of that; it would probably require a bit more state > tracking per zend_function so that we know that we need to do that > step during binding.
This gets incredibly complex not only to figure out what to do in the PHP source, but for scripters to figure out what the heck it does... If it's making YOUR head spin, what will it do to the poor unwashed masses?... Obviously, an anonymous function is going to be inherently complex -- but keep it as simple as it can be. I suspect that you could get away with JUST using global and/or static as they exist now, not introduce yet another scoping keyword, and anything that *NEEDS* to be done with an anonymous function can be done. Does anybody really *NEED* a variable whose scope is non-global and captured at the time of the func definition, carried over beyond the scope of that until it's executed?... Somehow I think you're just complicating it "because you can" rather than because anybody really NEEDS this. You have to have a pretty esoteric function to need that kind of scope control, no?
-- Some people have a "gift" link here. Know what I want? I want you to buy a CD from some starving artist. http://cdbaby.com/browse/from/lynch Yeah, I get a buck. So?

Stanislav Malyshev

19 years ago
> This gets incredibly complex not only to figure out what to do in the > PHP source, but for scripters to figure out what the heck it does...
Welcome to the world of closures :) But in most cases people use it to do pretty basic stuff (unless they are CS majors with too much time on their hands ;) - like creating "dynamic anonymous functions" - basically resulting in the same as what create_function does, and some currying - which, for those who doesn't know it, is technique of partially instantiating a multi-argument function - i.e. making something like: $addtwo = function ($a) { return $a+2; } $six = $addtwo(4); or more frequently something like this: $var = "foo"; $compare_to_var = function($s) { return (str_compare($var, $s)<0); } $strings_less_than_var = array_filter($array, $compare_to_var); which is really powerful technique for dynamic language, though can easily lead one to lose all track of what is happening if overused. For more confusion see http://en.wikipedia.org/wiki/Currying :)
> If it's making YOUR head spin, what will it do to the poor unwashed > masses?...
Unwashed masses better not do it :) Actually many "washed" masses have hard time to understand these things too.
> I suspect that you could get away with JUST using global and/or static > as they exist now, not introduce yet another scoping keyword, and > anything that *NEEDS* to be done with an anonymous function can be > done.
I guess this depends on definition of "NEEDS".
> You have to have a pretty esoteric function to need that kind of scope > control, no?
Depends on your background. Some people consider LISP intuitive language :) And if you work with Javascript, you probably would be doing it daily - most AJAX toolkits rely on heavy usage of anonymous functions. Not sure it needs to be in PHP though. It might be cool thing, but it's definitely becomes very confusing very fast.
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/

Chad Daelhousen

19 years ago
Richard Lynch wrote:
> I suspect that you could get away with JUST using global and/or static > as they exist now, not introduce yet another scoping keyword, and > anything that *NEEDS* to be done with an anonymous function can be > done. > > Does anybody really *NEED* a variable whose scope is non-global and > captured at the time of the func definition, carried over beyond the > scope of that until it's executed?... > > Somehow I think you're just complicating it "because you can" rather > than because anybody really NEEDS this.
Objects provide for functions with state (methods and properties), in a way that doesn't cause headaches with scoping. So although I would love the convenience of closures in certain places, I can't argue that there is a NEED for them.
-- Chad Daelhousen I've been programming for about 15 years, but it's only in the last couple that I've come to a real understanding of it all.

Richard Lynch

19 years ago
I think the anonymous name having metadata about the __FILE__ __LINE__ __COLUMN__ would be pretty nifty for error messages and debuggers... I'm a bit tired of seeing "Error: blah blah in Unknown on line: 0" personally. :-) This presumes somebody would take the effort to de-construct that metadata for a better error message, but better to have it available and possible to be done someday than "impossible"
-- Some people have a "gift" link here. Know what I want? I want you to buy a CD from some starving artist. http://cdbaby.com/browse/from/lynch Yeah, I get a buck. So?

Wez Furlong

19 years ago
My implementation preserves this information. --Wez. On Mar 19, 2007, at 5:26 PM, Richard Lynch wrote:

Stanislav Malyshev

19 years ago
> I think the anonymous name having metadata about the __FILE__ __LINE__ > __COLUMN__ would be pretty nifty for error messages and debuggers... > > I'm a bit tired of seeing "Error: blah blah in Unknown on line: 0" > personally. :-)
I'd say if it's compiled then the compiler would put there file and line numbers too, just as for the regular function.
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/

David Zülke

19 years ago
Am 19.03.2007 um 00:41 schrieb Wez Furlong:
> We've been daydreaming about the ability to do something like this > in PHP: > > $data = array("zoo", "orange", "car", "lemon", "apple"); > usort($data, function($a, $b) { return strcmp($a, $b); }); > var_dump($data); # data is sorted alphabetically > > So, the question is, do we want this in PHP?
Oh yes. Please. Please. Please :) David

Antony Dovgal

19 years ago
On 03/19/2007 02:41 AM, Wez Furlong wrote:
> We've been daydreaming about the ability to do something like this in > PHP:
I don't have any objections, the only requirement from me is that it should be covered by tests as much as possible. So I would like to encourage people to write tests to support the patch. If all the people saying "yes, please" write a test case and send it to the list, the coverage would be pretty good, I guess. Oh, and of course we can't include it into 5.2, it's only for HEAD (and maybe for 5.3, that's up to Ilia).
-- Wbr, Antony Dovgal

Sebastian Bergmann

19 years ago
Wez Furlong wrote:
> So, the question is, do we want this in PHP?
Yes, please. (It might even make my userland implementation of of CLOS- style generic functions easier.)
-- Sebastian Bergmann http://sebastian-bergmann.de/ GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

Richard Lynch

19 years ago
On Sun, March 18, 2007 6:41 pm, Wez Furlong wrote:
> We've been daydreaming about the ability to do something like this in > PHP: > > $data = array("zoo", "orange", "car", "lemon", "apple"); > usort($data, function($a, $b) { return strcmp($a, $b); }); > var_dump($data); # data is sorted alphabetically
I'd LOVE it if there was SOME difference between this and a normal 'function' definition... I guess we're kind of stuck with 'create_function' being the mess that it is. But perhaps something like 'temp_function' or 'local_function' or 'lexical_closure' or something similar. Even 'horse' [*] would be fine by me. I think it muddies things too much to have it just be 'function' with no name after it. +1 * [sings] "In the desert, on a horse with no name"
-- Some people have a "gift" link here. Know what I want? I want you to buy a CD from some starving artist. http://cdbaby.com/browse/from/lynch Yeah, I get a buck. So?

Robert Cummings

19 years ago
On Mon, 2007-03-19 at 15:20 -0500, Richard Lynch wrote:
> On Sun, March 18, 2007 6:41 pm, Wez Furlong wrote: > > We've been daydreaming about the ability to do something like this in > > PHP: > > > > $data = array("zoo", "orange", "car", "lemon", "apple"); > > usort($data, function($a, $b) { return strcmp($a, $b); }); > > var_dump($data); # data is sorted alphabetically > > I'd LOVE it if there was SOME difference between this and a normal > 'function' definition... > > I guess we're kind of stuck with 'create_function' being the mess that > it is. > > But perhaps something like 'temp_function' or 'local_function' or > 'lexical_closure' or something similar. Even 'horse' [*] would be > fine by me. > > I think it muddies things too much to have it just be 'function' with > no name after it. > > +1
A function with a name is no longer anonymous ;) Cheers, Rob.
-- .------------------------------------------------------------. | InterJinn Application Framework - http://www.interjinn.com | :------------------------------------------------------------: | An application and templating framework for PHP. Boasting | | a powerful, scalable system for accessing system services | | such as forms, properties, sessions, and caches. InterJinn | | also provides an extremely flexible architecture for | | creating re-usable components quickly and easily. | `------------------------------------------------------------'

Richard Lynch

19 years ago
On Mon, March 19, 2007 3:35 pm, Robert Cummings wrote:
> On Mon, 2007-03-19 at 15:20 -0500, Richard Lynch wrote: >> On Sun, March 18, 2007 6:41 pm, Wez Furlong wrote: >> > We've been daydreaming about the ability to do something like this >> in >> > PHP: >> > >> > $data = array("zoo", "orange", "car", "lemon", "apple"); >> > usort($data, function($a, $b) { return strcmp($a, $b); }); >> > var_dump($data); # data is sorted alphabetically >> >> I'd LOVE it if there was SOME difference between this and a normal >> 'function' definition... >> >> I guess we're kind of stuck with 'create_function' being the mess >> that >> it is. >> >> But perhaps something like 'temp_function' or 'local_function' or >> 'lexical_closure' or something similar. Even 'horse' [*] would be >> fine by me. >> >> I think it muddies things too much to have it just be 'function' >> with >> no name after it. >> >> +1 > > A function with a name is no longer anonymous ;)
I am not suggesting that there be a name. I am suggesting that the reserved keyword for an anonymous function should not be 'function', the same as a normal function.
-- Some people have a "gift" link here. Know what I want? I want you to buy a CD from some starving artist. http://cdbaby.com/browse/from/lynch Yeah, I get a buck. So?

Daniel Rozsnyo

19 years ago
Richard Lynch wrote:
> On Mon, March 19, 2007 3:35 pm, Robert Cummings wrote: >> On Mon, 2007-03-19 at 15:20 -0500, Richard Lynch wrote: >>> On Sun, March 18, 2007 6:41 pm, Wez Furlong wrote: >>>> We've been daydreaming about the ability to do something like this >>> in >>>> PHP: >>>> >>>> $data = array("zoo", "orange", "car", "lemon", "apple"); >>>> usort($data, function($a, $b) { return strcmp($a, $b); }); >>>> var_dump($data); # data is sorted alphabetically >>> I'd LOVE it if there was SOME difference between this and a normal >>> 'function' definition... >>> >>> I guess we're kind of stuck with 'create_function' being the mess >>> that >>> it is. >>> >>> But perhaps something like 'temp_function' or 'local_function' or >>> 'lexical_closure' or something similar. Even 'horse' [*] would be >>> fine by me. >>> >>> I think it muddies things too much to have it just be 'function' >>> with >>> no name after it. >>> >>> +1 >> A function with a name is no longer anonymous ;) > > I am not suggesting that there be a name. > > I am suggesting that the reserved keyword for an anonymous function > should not be 'function', the same as a normal function. >
I don't have anything against 'function', I think JS uses the same syntax - function without a name. If you change it to something different, e.g 'callback', then you loose the information that it is actually a function $error_func = callback($msg) { file_put_contents('php://stderr',"Error: $msg\n"); } vs. $error_func = function($msg) { file_put_contents('php://stderr',"Error: $msg\n"); } The second one looks better for me.

David Zülke

19 years ago
Am 20.03.2007 um 15:24 schrieb Daniel Rozsnyo:
>>> A function with a name is no longer anonymous ;) >> I am not suggesting that there be a name. >> I am suggesting that the reserved keyword for an anonymous function >> should not be 'function', the same as a normal function. > > I don't have anything against 'function', I think JS uses the same > syntax - function without a name. If you change it to something > different, e.g 'callback', then you loose the information that it > is actually a function > > $error_func = callback($msg) { > file_put_contents('php://stderr',"Error: $msg\n"); > } > > vs. > > $error_func = function($msg) { > file_put_contents('php://stderr',"Error: $msg\n"); > } > > The second one looks better for me.
what about "lambda", like in Python? David

Stanislav Malyshev

19 years ago
> what about "lambda", like in Python?
To most people without CS theory background lambda does not tell anything, to people that have this background lambda reminds of LISP - and I'm not sure this is better :)
-- Stanislav Malyshev, Zend Products Engineer stas@zend.com http://www.zend.com/

David Zülke

19 years ago
Am 20.03.2007 um 23:42 schrieb Stanislav Malyshev:
>> what about "lambda", like in Python? > > To most people without CS theory background lambda does not tell > anything, to people that have this background lambda reminds of > LISP - and I'm not sure this is better :)
Excellent! That means people will maybe look it up to learn what a lambda is before they use it, just what PHP needs ;) Seriously though, my suggestion is nonsense because anonymous functions in PHP wouldn't be restricted to a single expression, which is the case with lambdas. David

Andrei Zmievski

19 years ago
Yes, with whipped cream on top. -Andrei On Mar 18, 2007, at 4:41 PM, Wez Furlong wrote: