$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.
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
yes, please.
Jan
--
I'm poking to find an elegant way to fix that.
--Wez.
On Mar 18, 2007, at 7:41 PM, Wez Furlong wrote:
> You can find my prototype patch at http://pastebin.ca/400871
> (against PHP_5_2)
> 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?
>
> 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)
------=_Part_69570_26017896.1174265129361--
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."
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.
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
st...@zend.com http://www.zend.com/
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."
--
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:
>> $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
> st...@zend.com http://www.zend.com/
>
--
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).
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
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.
> 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
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
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
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
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
> 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.
--
> 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/)
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
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
st...@zend.com http://www.zend.com/
--
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
$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.
> 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.)
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
st...@zend.com http://www.zend.com/
--
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?
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.
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. |
`------------------------------------------------------------'
A function with a name is no longer anonymous ;)
> 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.
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?
--
How you are going to know where "parent scope" is? It can even be not
existing anymore, or can be separated by any number of parameter
passing. Remember that the function is defined at compile-time, but
invoked at run-time by some other function.
--
Stanislav Malyshev, Zend Products Engineer
st...@zend.com http://www.zend.com/
--
Global is not handled this way. Global creates reference at runtime
(i.e. when function is *executed*) to runtime variable in global space.
However, binding to compile scope can't work as globals do - since
binding should happen at "definition run-time" - e.g., when the function
definition is used. Adding binding capabilities to DECLARE_FUNCTION
might work though, but it is not clear what to do in case this is
declared in a loop (then it can't really be done compile-time unless we
clone this function each time). It must be also considered how these
values are added to the function symbol table when the function runs -
e.g. are they references or copies?
I guess I was primarily thinking in the context of the anonymous
function being defined in your previous example. As such the parent
scope is known (or at least can be expected), unless (unknown to me)
within the internal C code the scope can change other than the hierarchy
one would see visually while writing PHP code. From your example:
On Sun, 2007-03-18 at 19:06 -0700, Stanislav Malyshev wrote:
>
> 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
>
We would have:
<?php
$data = array("zoo", "orange", "car", "lemon", "apple");
$rev = 1;
usort($data, function($a, $b) { return seek_var( 'rev' )?strcmp($a,
$b):!strcmp($a,
$b); });
var_dump($data); # data is sorted alphabetically
?>
Can we not expect that the lexical scope of the $rev is the immediate
parent of the anonymous function at runtime? Obviously this could also
work for normally defined functions if there's an expectation of the
calling environment having some specific variable defined.
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. |
`------------------------------------------------------------'
--
It is known in compile-time. But functions are not called in
compile-time. And in run-time, inside usort() - which could in other
case be some kind of foo_sort() passing its second parameter to a dozen
of other functions, one of which uses it to invoke comparator function -
you can not know where the scope in which usort was called is with
regard to the scope of the executing anonymous function. And if you took
this function name and saved it in the variable - it could be that the
scope it was defined in does not exist anymore.
--
Stanislav Malyshev, Zend Products Engineer
st...@zend.com http://www.zend.com/
--
I'm not arguing the preservation of the exact value of $rev when the
anonymous function was created (as would be the case with a closure).
I'm thinking of the variable being whatever is defined in the parent
regardless. As in my proposal, the seek could search all the way up to
the top in which case the $rev would be found if it had been defined as
expected. At any rate, I guess this is diverging from the real
discussion of anonymous functions :)
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. |
`------------------------------------------------------------'
--
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.
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?
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
st...@zend.com http://www.zend.com/
--
Then it has 1 level to travel to the top since it's own scope isn't the
global scope.
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. |
`------------------------------------------------------------'
--
If you've ever tried to hack on the source to anything that you didn't
write that also uses globals throughout (Gallery2, for example), you
know how hard it is to track down a single layer of scope that can be
defined [somewhere else].
Tracking this up the chain like a bubbled exception sounds like a
nightmare for debugging/comprehension, and IMO it's too magical.
One layer of scope might be useful: $_PARENT ?
More than that, and my head starts to hurt.
S
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
st...@zend.com http://www.zend.com/
--
$var =3D php_version();
$fancyVer =3D function () { return "PHP $_SCOPE['ver']; };
So what this does is compile the "anonymous function" at compile-time,
but when this line is executed (note, this line of code should also be
reached during execution), then we do the fix-up for $_SCOPE variables.
Regular variables remain what they would in create_function(). Fix-up
time would be faster than compiling the code.
Thoughts?
Andi
Yes, this is basically what Wez was proposing I guess. This would
require new hashtable for _SCOPE (and/or adding _SCOPE elements on
execution of anon-func line) in the function run-time data.
> Thoughts?
This might work, still not sure if we really want that in PHP. On one
side, it's cool, on other side closures can develop into a very messy
code :)
--
Stanislav Malyshev, Zend Products Engineer
st...@zend.com http://www.zend.com/
--
>> Thoughts?
>
> This might work, still not sure if we really want that in PHP. On one
> side, it's cool, on other side closures can develop into a very messy
> code :)
Yeah well .. for the single task of callbacks they are great and prevent
a lot of messiness .. I think its messy to pollute the namespace for
something which is not intended for reuse .. maybe we need to
artificially limit its uses just like for "goto".
regards,
Lukas
> -----Original Message-----
> From: Lukas Kahwe Smith [mailto:m...@pooteeweet.org]=20
> Sent: Monday, March 19, 2007 3:08 PM
> To: Stas Malyshev
> Cc: Andi Gutmans; Robert Cummings; Wez Furlong; Sean Coates;=20
> inte...@lists.php.net
> Subject: Re: [PHP-DEV] PATCH: anonymous functions in PHP
>=20
> Stanislav Malyshev wrote:
>=20
> >> Thoughts?
> >=20
> > This might work, still not sure if we really want that in=20
> PHP. On one=20
> > side, it's cool, on other side closures can develop into a=20
> very messy=20
> > code :)
>=20
> Yeah well .. for the single task of callbacks they are great=20
> and prevent a lot of messiness .. I think its messy to=20
> pollute the namespace for something which is not intended for=20
> reuse .. maybe we need to artificially limit its uses just=20
> like for "goto".
>=20
> regards,
> Lukas
>=20
I almost finished my MS in CS with Artificial Intelligence
concentration at DePaul, so I *was* one of those CS students with too
much time on my hands.
Then I worked at an AI think tank lab at Northwestern University for
most of a decade using Lisp.
I gotta say that while it was Really Nifty to know all about those
esoteric closures, curries, and whatnot I have since forgot, mostly, I
didn't need these things on a daily basis even at that job.
So, yes, somebody somewhere "needs" this, but is it the kind of thing
that belongs in PHP?
I think not.
By "this" I mean the ability to have the lexical closure carry its
scope around with itself.
I *WANT* to have a simple clean anonymous function syntax.
Can't you just take the body of "create_function" with the syntax of
the patch, and marry those two?
How does the current create_function handle this same scope issue?
--
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?
--
Well, that'd be a bit hard since the whole difference is that
create_function is runtime (thus having access to run-time values) while
anon-func we are trying to do here is compile-time (at least it makes a
lot of sense to do it compile-time). We could of course just leave the
scope thing alone and say "want access to other scope? tough luck, use
create_function/eval or globals".
> How does the current create_function handle this same scope issue?
It doesn't AFAIK :) Since it's a close relative of eval, it can import
values of variables by inserting ones into function string, but nothing
more (i.e. you couldn't put an object there, and couldn't refer to a
variable - only insert it's value).
--
Stanislav Malyshev, Zend Products Engineer
st...@zend.com http://www.zend.com/
--
I already explained why this can't work, in this very thread. At least
not without hacking { and } to work (mostly) like " in this context.
> How does the current create_function handle this same scope issue?
create_function() takes a string. This string is interpolated at
runtime. There's an obvious distinction between local variables (they
look like \$something within the string, and parent vars: they look like
'. $var .' )
S
I thought the original driving purpose was to not have the gnarly
quoting mess of create_function.
Yes, in the implementation, it turned out to be a compile-time closure.
Does that mean we really WANT to go there, just because it falls out
easily, or does that mean we should step back and look at the original
goal and see if maybe we've gone off-track?
>> How does the current create_function handle this same scope issue?
>
> It doesn't AFAIK :) Since it's a close relative of eval, it can import
> values of variables by inserting ones into function string, but
> nothing
> more (i.e. you couldn't put an object there, and couldn't refer to a
> variable - only insert it's value).
I'd be perfectly happy if PHP's "anonymous" functions had the nice
syntax and no funky weird stuff about closure, a la
eval/create_function, personally.
I don't need the closures, but when I need a quickie anon function in
PHP, I just want something less ugly than create_function.
That's just my personal preference, of course.
--
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?
--
Well I did originally suggest defaulting to the parent scope with
options for advanced users to climb higher :) Just because there are
unwashed masses as Richard Lynch likes to call it, doesn't mean we all
need to suffer their limitations.
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. |
`------------------------------------------------------------'
--
While the discussion about closures and how to emulate them was
interesting I think Richard hits the nail on the head.
1. Keep it simple as in Wez' patch.
2. Maybe make it return a callback array (object, method) if used with
class to be able to use $this.
3. Maybe add $_SCOPE a la Andi's proposal if you really think it's
worthwhile.
My two cents,
- Chris