Hello,
On Tue, Jan 13, 2009 at 1:30 PM, moo.tinys <[email protected]> wrote:
> this topic may be discussed before, but i'd bring it up again.
>
> closure was introduced in PHP 5.3, function with its context can now
> be stored in an callable object(or a handler in string type, whatever)
> i think it's easy and read to introduce generator and yield operator
> in php
>
> let's see what was in Iterator:
> 1. every class/interface can be prototyped in php userland, not
> internal, although many of the them was builtin written in c so make
> life easier
> pro: "simple" to implement in ZendEngine, see note 2 aboive
> con: really ugly to code Iterator/Filter in userland, hard to
> understand how they worked, code has to be split in rewind/next
> functions
> 2. no changes is required in ZendEngine, except powering up "foreach"
> to support iterator, so ppl can iterate over it much more easier.
On the contrary, It will most likely require a lot of changes to
provide structures that are able to store their execution context to
be able to resume it later. I.e.
function foo() {
error_reporting(0);
yield "foo";
trigger_error("foo", E_NOTICE);
yield "bar";
}
$e = false;
error_reporting(E_ALL);
foreach (foo() as $b) {
if (!$e) { $e = true; error_reporting(E_ALL); }
}
1) will the error be thrown?
2) what will the error_reporting value be after the execution of the function ?
error_reporting is a setting that is shared, and here you'd like to
resume the execution using the old context (error_reporting = 0) to
continue the function, affecting the outer context, which will stick
after the function ends? Or do you plan to keep both contexts
completely separated and create inconsistencies?
> pro: "simple" to implement in ZendEngine, see note 2 aboive
> con: -
>
> let's see what will yeild/generator looks like:
> 1. require saving function calling context (not call stack)
> con(was): there was no way to save it, we had to implement it first
> con(now): no con, implemented already in 5.3
How is that implemented already in 5.3 ?
> 2. just 1 function, yield at any where in the body
> pro: much more readable than Iterator
> con: "yield" is now reserved keyword
> example:
> function foo($space_and_new_line = false)
> {
> yield "hello";
> if ($space_and_new_line) {
> yield " ";
> }
> yield "world";
> if ($space_and_new_line) {
> yield PHP_EOL;
> }
> }
>
> $g = foo(true); // function foo() is not called here
> foreach ($g as $i) { // function foo() IS called here
> echo $i;
> }
>
> function filter($g, $regex)
> {
> foreach ($g as $baa) {
> if (preg_match($regex, $i)) {
> return true;
> } // if
> } // foreach
> }
>
> $g = foo(true);
> foreach (filter($g, "^\\w+$") as $i) {
> echo $i; // now letters only
> }
That example looks wrong(and I hope it is):
- $i is not defined in the scope of filter()
- filter() returns true or null. You can't iterate on such values.
Also, could you provide an example where this construct is actually useful ?
The example you provided doesn't demonstrate anything, as it can be
implemented in a far easier way using:
function foo($s) {
return $s ? array('hello', ' ', 'world', PHP_EOL) : array('hello', 'world');
}
foreach(foo() as $word) {
...
}
additionally, SPL's filterIterator and arrayiterator can be used to
implement a filtered iteration on the array.
>
> $g = foo(true);
> echo $g(); // same as: echo $g->value(); $g->next(); this is not in
> python, neither in php iterator
> echo $g();
> echo $g();
This syntax is definitely not self-explanatory, and will make things
really hard to understand.
> (btw, i think iterator should be able to be used in this way)
>
> I don't think you can reimplement it into Iterator in any simpler
> form, except that you can reuse those classes already implemented.
>
> is it perl way? no. because yield/generator make code much more
> readable, easier to understood, not just "easier" to write, it's the
> php way
>
> ==========
> for those who don't know what yield/generator is, you can see python
> document or the following brief (correct me if i'm wrong)
> . functions (named or unamed/closure) with yield in its body, is a
> generator function that with context saved, not a normal. it's similar
> as closure context but with "yield point" saved
> . when you call a generator function, it returns an generator object
> . the interface to generator object is exactly like Iterator
> interface, that can be design to have rewind/next/valid methods, etc
> . generator is an OuterIterator
> . you can call $generator->next() (and other methods) explicitly, or
> call foreach which call iterator/generator methods implictly
> . the only difference between iterator and generator is how they
> implement it inside. when php execute "yield", the generator is
> execution is returned but its execution context is saved, next time
> the generator is iterated, php execute from the last yield point with
> all context restored.
I'm skeptic at what value this construct would really add to PHP. And
my guess is, it will not be worth the trouble implementing it.
Regards,
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>
>
>
--
Etienne Kneuss
http://www.colder.ch
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php