Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:96653 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 30220 invoked from network); 30 Oct 2016 15:08:45 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 30 Oct 2016 15:08:45 -0000 Authentication-Results: pb1.pair.com header.from=rasmus@mindplay.dk; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=rasmus@mindplay.dk; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain mindplay.dk from 209.85.217.170 cause and error) X-PHP-List-Original-Sender: rasmus@mindplay.dk X-Host-Fingerprint: 209.85.217.170 mail-ua0-f170.google.com Received: from [209.85.217.170] ([209.85.217.170:35683] helo=mail-ua0-f170.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 56/F2-25911-BFC06185 for ; Sun, 30 Oct 2016 10:08:45 -0500 Received: by mail-ua0-f170.google.com with SMTP id 12so87905408uas.2 for ; Sun, 30 Oct 2016 08:08:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mindplay-dk.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=3F8Wbxp9IB8Gh66qoGgkOZF/JAFc8otpQ22ZYEUL+NQ=; b=WRG8Guo4F2dmJb+pEj8ZeJ5jPmgCUBve5ILFRoHPFdmiVTf7kCJU1EiVhqAzhArwDW uVskAwl0zhypxkiGpdvioAuLQcFBmjTexgw34lte7kM146HDAYLSc2GAsgsVA4g1z47S ijgdjDWQy2FpRVtgI0l3BE1Nj5DMbuTtCwX+7sdoxJMmTSO0uGjS5g1dp3MYS2EXtACQ BCp9WF3/9Q+HzyIQPMgJeSVdIGefmCZDJDAIMsg+vpPB7411l7MjrMwBrD3WHGoDr4jk Vxw7yAvhgMxLb6VCNEHDpJ1N1k9z5ixWv4NgZ2pCbm8Clh3fm8ZLMXcqYc4wKOmjtdiv 8lsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=3F8Wbxp9IB8Gh66qoGgkOZF/JAFc8otpQ22ZYEUL+NQ=; b=a6y7qyq+9bfGbxDio3Gtf0yj6mUdpRZWTj1fBZzLEGvVgvppD+2FVChbPXKMkg/RXI 7cpLuQ4SSFR/hxlaEDxEo1tJAhPjnwsdFyLsO6nNBafQQ1x6gXR1xzHGK8aLEPnz7fCs ahfINTBxdFKqWPWSSoZJUnjDinYn2b0fYDYkm/DqfWvVT7jmN0GdXzL/Ebub6gsJdFUF 8NR4fL22v+kBeORbyGXND04LzqCO2QkOknkEr2c1VRJeMRY7BSIDcEvPxbTlEJYFuy++ Q8WsPOaFd0nKcFRj0Svw89vLM6K9bIfb0IgoX/+LDImR9touT0m+zQrXs2KKFGo7L44S aSVA== X-Gm-Message-State: ABUngvehOdyViUDrZtc54fIjhPri8z6W12tuCwgmrLJSoxO3eVn3s6eWDhKHVJ932TMK5+juKlQ6wTdOPSTtHQ== X-Received: by 10.176.5.130 with SMTP id e2mr20145801uae.108.1477840121542; Sun, 30 Oct 2016 08:08:41 -0700 (PDT) MIME-Version: 1.0 Received: by 10.103.99.4 with HTTP; Sun, 30 Oct 2016 08:08:40 -0700 (PDT) In-Reply-To: <402447f2-6007-95c4-6b1d-2bbb30dfdd1d@fleshgrinder.com> References: <44244cfd-c8ad-e0a9-4e70-380a8a8c940c@syberisle.net> <01f2f3da-592b-fd23-709d-ad620422f56d@fleshgrinder.com> <402447f2-6007-95c4-6b1d-2bbb30dfdd1d@fleshgrinder.com> Date: Sun, 30 Oct 2016 16:08:40 +0100 Message-ID: To: PHP internals Cc: Nikita Popov , Levi Morrison , David Lundgren Content-Type: text/plain; charset=UTF-8 Subject: Re: [PHP-DEV] Allow Iterator to be used with current, next, reset, key functions From: rasmus@mindplay.dk (Rasmus Schultz) > What I am concerned with is the opt-out case of this functionality. What > if I do not want that somebody misuses an unbuffered result set in such > a way: selecting 1,000 records just to throw 998 away In my opinion, that's a completely hypothetical use-case. If I fetched 1000 records, most likely I'm doing something with those 1000 records. If I happen to also be doing something special with the first or last record, why should that require anything special from the collection object itself? If we're really this concerned about someone misunderstanding these functions, I think honestly it would be better to not support traversables at all - e.g. force them to use iterator_to_array() instead, which makes it very obvious what's happening. Perhaps that's a better solution altogether. It also fixes the case where you accidentally traverse an open record-set twice, e.g. calling first() and last() on the same iterable - that's not a problem case you can fix, not even with an interface. In that case, the correct thing is to fetch the records first, and/or adjust your query, depends on the use-case, but accidentally iterating twice is likely never the desired side-effect. > Another case is every unsorted form of collection, what is first, what is last? Hypothetical. If it doesn't matter what's first or last, such as in an unsorted form collection, why would you be calling the first or last functions? > How to you determine first and last if the keys of a traversable are objects? They're the first and last items to come out of the traversable. Seems pretty straight forward to me. But either way, I think I'm changing my mind about this one. And if the these functions support only arrays, then also the names should probably be array_first() and array_last() for consistency with other array-only functions. Perhaps better to make people be explicit, rather than trying to hide side-effects to achieve shorter syntax... On Sun, Oct 30, 2016 at 2:14 PM, Fleshgrinder wrote: > On 10/30/2016 1:59 PM, Rasmus Schultz wrote: >> I think you misunderstand. >> >> I'm only suggesting that implementing first/last explicitly as an >> optimization be optional. >> >> If you call first() or last() on a traversable that doesn't implement >> this interface, it will simply traverse the first item or traverse to >> the end. >> >> In other words, it'll always work, so it doesn't violate anything. >> >> As said, in a lot of cases, such as traversing a stream of database >> records, there *is* no optimization you can make for last() because >> that's not possible with the driver. >> >> So in that case, what you're proposing, is that all existing >> traversables, such as DB adapters, shouldn't work with these functions >> at all - everyone should have to go and implement this interface >> first, even for traversable record sets where no optimization can be >> made anyway and all you can do is actually fast-forward to the last >> record by traversing the whole result set anyhow. >> >> The only thing you'll get by forcing implementation of this interface, >> is no existing traversable will work with these functions. >> >> In addition, when everyone starts implementing this interface, those >> libraries will lose backwards compatibility, since that interface will >> not be available on older versions. >> >> All so you can force people to implement an interface that, in many >> cases, contains redundant code that simply traverses the entire result >> set to the last item and returns it, for no meaningful reason. >> > > What I am concerned with is the opt-out case of this functionality. What > if I do not want that somebody misuses an unbuffered result set in such > a way: selecting 1,000 records just to throw 998 away. Your proposal is > very appealing in many ways but the opt-out means that I now need to > trigger a notice or throw an exception because there is no other way to > disallow this functionality. > > Especially in the light of unbuffered result sets and generators which > can be traversed only once. > > Another case is every unsorted form of collection, what is first, what > is last? How to you determine first and last if the keys of a > traversable are objects? Fail? > > There are too many open questions in this regard. It's easier with the > primitive arrays because they have their limitations clearly defined > (maps keep insert order). > > First and last only make sense for certain data structures but not for > all. Implementing something that just works might work for 80 % but not > for the rest and they have the problem now. I know that we have no means > to express proper data structures but this will not make it better. > Whether it makes it worse is another question that might help to decide. > > -- > Richard "Fleshgrinder" Fussenegger