Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:96649 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 18757 invoked from network); 30 Oct 2016 12:59:47 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 30 Oct 2016 12:59:47 -0000 Authentication-Results: pb1.pair.com smtp.mail=rasmus@mindplay.dk; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=rasmus@mindplay.dk; sender-id=unknown Received-SPF: error (pb1.pair.com: domain mindplay.dk from 209.85.217.182 cause and error) X-PHP-List-Original-Sender: rasmus@mindplay.dk X-Host-Fingerprint: 209.85.217.182 mail-ua0-f182.google.com Received: from [209.85.217.182] ([209.85.217.182:36607] helo=mail-ua0-f182.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 68/21-25911-2CEE5185 for ; Sun, 30 Oct 2016 07:59:46 -0500 Received: by mail-ua0-f182.google.com with SMTP id b35so14922229uaa.3 for ; Sun, 30 Oct 2016 05:59:46 -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=GhsU6V6ZVS7T18tZRqebw1PNM21FK4VagLJZJuTEgjI=; b=UTsYn6fYH63UWL2f5wDFMb8MBcDLsyzQqaGTXfpV2kND6wixa0fdtJSW75hsNuMrqx oUztoaAoazgIttkh2wsKmuEaoCYuPBoTrV3BpS2bZ2O2VDz3dcdal5aal5LoKybpIQuR ++RyShQo8XwuhwjBu/Eqk4l/hZdx2y5/ung+XDDUxxY15viBm5ovPZZ7Z/DpGjzDLP0V e12hzPmmK2c1A0gWZzBVX/Ulh4XDIo5OO5ohFBR5d3OHRCtfRHDXyNDtkkDpsA14o+n9 SGkyQPRLukI67cxwCEMmzyYrDvztU+C+tSJW+fw1qwbYXzFU4qnw1dhxzlUZSB+P8N16 5tLw== 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=GhsU6V6ZVS7T18tZRqebw1PNM21FK4VagLJZJuTEgjI=; b=IHcX31w/ASOu5xY5MKaFzyrZFMRN7vALa5JCLvahs2abgI45PuoIhmVoclaan79IvF ZhNiURC5BucnWCzAeMT67GMm1Nx5HTCPPPhH08sjK6gPbH7dPA9M1KLXrwj8MyZOX8Ts /XSsfir5Nt4fo73BuArNOk8cUPd7njRQeK/S3zlVtW5iJsM3fnsdQGeqfjrELxQ45iY2 iTO4lZ1FpqIjMt2Tr1K4z+OwsoJikwruM+cstrbnZhA8ZZwtZq1PSsMrYWxoWObzzRzZ Rq/MCFieT8fJd2f+iMyPW/71Fh/vdoZXRDVsgCAc3XAkodMsUkhcsd7AZZVymr7bOLQe MWNQ== X-Gm-Message-State: ABUngveMnicGLTqrlzrP4axu8evtmg8zqpi1AT49cXHO3kPebZusXph+VuQeC4shqkVcIS9XZWK2SoI1FTc4Ng== X-Received: by 10.159.51.9 with SMTP id o9mr19246237uab.155.1477832382527; Sun, 30 Oct 2016 05:59:42 -0700 (PDT) MIME-Version: 1.0 Received: by 10.103.99.4 with HTTP; Sun, 30 Oct 2016 05:59:42 -0700 (PDT) In-Reply-To: References: <44244cfd-c8ad-e0a9-4e70-380a8a8c940c@syberisle.net> <01f2f3da-592b-fd23-709d-ad620422f56d@fleshgrinder.com> Date: Sun, 30 Oct 2016 13:59:42 +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) 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. On Sun, Oct 30, 2016 at 1:47 PM, Fleshgrinder wrote: > On 10/30/2016 1:31 PM, Rasmus Schultz wrote: >> On second thought, I agree with that - changing reset() and end() >> doesn't make sense, because people know them and expect them to work >> in a certain way. Likely a lot of people would actually continue to >> use them with intermediary variables the way they do today. Better >> to introduce a new pair of functions, since this will make it clear >> when consumer code depends on the new behavior - if we update the >> existing functions, that means you have to read code knowing which >> version of these very common (and very old) functions you were >> expecting to call. >> >> One thing though, since we have to introduce new functions, I would >> not suggest these be array_first() and array_last(), but rather >> simply first() and last(), and make then work with anything iterable, >> not just arrays. >> > > `first()` and `last()` are extremely generic names and I am still hoping > to see nikic's scalar objects extension to land in core before 8. In > this case one would always call `$x->first()` and `$x->last()`. > Continuing with the `array_` prefix makes perfect sense to me, even if > they accept `\Traversable` instances as well. We also expect `str_` > prefixed functions to accept stringable objects, dont' we. It's just a > prefix for grouping and not necessarily a restrictions regarding the > types the function accepts. > > On 10/30/2016 1:31 PM, Rasmus Schultz wrote: >>> Retrieving the first and last would mean to iterate all the >>> results. >> >> Well, retrieving the last would - retrieving the first would mean >> iterating only over the first result. For a lot of use-cases, and >> unbuffered database results in particular, this is precisely what >> you'd want. >> >>> An additional interface should be required for traversables in >>> order to work with first and last. >> >> I think it would be great to have that as an option - for cases >> where you can and want to optimize retrieval of the last item, but I >> don't think it should be required? For example, in the case of an >> unbuffered database query, there is likely no optimization that can >> be made for last() in the first place, since the database >> client/server are likely using a protocol that doesn't even allow you >> to skip to the last result; in that case, requiring everyone to >> implement a new interface, which does nothing, isn't meaningful. >> > > Not requiring the interface means that we violate the Liskow's > substitution principle, something I see too often in core and successful > PHP software out there. What if a traversable does not want the first > and last to be retrieved in this manner? Throw an exception? This > violates the principle since it is not expected to behave in this way. > Another possibility would it be to return null but then the question is, > was null returned because the first or last element is null or because I > cannot retrieve the first and last. > > Making it explicit is much better. > > -- > Richard "Fleshgrinder" Fussenegger