Hello, On Tue, Jan 13, 2009 at 1:30 PM, moo.tinys <moo.ti...@gmail.com> 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