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

Reply via email to