Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:42603 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 34793 invoked from network); 13 Jan 2009 14:29:30 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 13 Jan 2009 14:29:30 -0000 Authentication-Results: pb1.pair.com smtp.mail=ekneuss@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=ekneuss@gmail.com; sender-id=pass; domainkeys=bad Received-SPF: pass (pb1.pair.com: domain gmail.com designates 72.14.220.152 as permitted sender) DomainKey-Status: bad X-DomainKeys: Ecelerity dk_validate implementing draft-delany-domainkeys-base-01 X-PHP-List-Original-Sender: ekneuss@gmail.com X-Host-Fingerprint: 72.14.220.152 fg-out-1718.google.com Received: from [72.14.220.152] ([72.14.220.152:46093] helo=fg-out-1718.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 50/00-42308-945AC694 for ; Tue, 13 Jan 2009 09:29:29 -0500 Received: by fg-out-1718.google.com with SMTP id 16so35308fgg.23 for ; Tue, 13 Jan 2009 06:29:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:sender :to:subject:cc:in-reply-to:mime-version:content-type :content-transfer-encoding:content-disposition:references :x-google-sender-auth; bh=R15NpbA/YGdMLKikP9zoGPvOnHYDtxI6kY4r2dztO6k=; b=v419SzkJMooQRUsAmhSnXvTQ/Was2iNfIrfy2m+NklhtXJFUHYyajArcLVwMwRFVHl QCX4lA1ZtqSACIJGu0gDAjThJUPF0vOEJ0viBXAxl7T4x1eBVbGp3pacE+CBi9t4W09O BiAkdFtV66jXmEUJY0wXm0aePF8kEVUA0hhHU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:sender:to:subject:cc:in-reply-to:mime-version :content-type:content-transfer-encoding:content-disposition :references:x-google-sender-auth; b=UOXYy+LEricU1ihbh/0w1mU1/r4P1UpF8/jtevVD4m7U11ODWAmz13PKu2UD3nKF2X QWffoWwle6zixXjBvru5fg80wtwTCgCuN0+SUq/QOpRExvJ89pAL0yREnY1ve5IcC8Uu SeD2l6olGYAl1boNnjqHKvgIA7OzdwSRuMzi0= Received: by 10.86.100.19 with SMTP id x19mr17628510fgb.29.1231856966680; Tue, 13 Jan 2009 06:29:26 -0800 (PST) Received: by 10.86.35.9 with HTTP; Tue, 13 Jan 2009 06:29:26 -0800 (PST) Message-ID: Date: Tue, 13 Jan 2009 15:29:26 +0100 Sender: ekneuss@gmail.com To: moo.tinys Cc: "PHP Developers Mailing List" In-Reply-To: <28139bc0901130430s32b0a156r792c39d2393e20c6@mail.gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline References: <28139bc0901130430s32b0a156r792c39d2393e20c6@mail.gmail.com> X-Google-Sender-Auth: 38cee9a36d740a28 Subject: Re: [PHP-DEV] generator/yield operator feature request From: webmaster@colder.ch ("Etienne Kneuss") Hello, On Tue, Jan 13, 2009 at 1:30 PM, moo.tinys 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