Hi

On 28/03/2023 14:42, G. P. B. wrote:
> On Tue, 28 Mar 2023 at 08:19, Christian Schneider <cschn...@cschneid.com>
> wrote:
> 
>> Am 28.03.2023 um 00:36 schrieb G. P. B. <george.bany...@gmail.com>:
>>> I therefore propose the "Define proper semantics for range() function"
>> RFC
>>> to address the unintuitive behaviour that sees no usage and/or hide bugs:
>>> https://wiki.php.net/rfc/proper-range-semantics
>>>
>>> The change propose to throw TypeErrors and ValueErrors for case where I
>>> couldn't find occurrences in the wild and hide bugs, and emit some
>>> E_WARNINGs for cases that are hard to detect via static analysis.
>>
>> I think it makes sense to clean up the range() function, thanks!
>>
>> There are two cases I would handle differently:
>> - I'm not sure why a negative step for $start > $end is considered wrong,
>> I consider range(10, 0, -2) at least as logical/readable as using a
>> positive decrement of 2. Not requiring a sign for steps seems weirder to me
>> but that's something we cannot change. *BUT* if it is the result of a
>> calculation it seems wrong to require an abs() around it. I do see the
>> reason for a warning/error when $start < $end and $step < 0.
>>
> 
> Considering the only other programming language that I know of that has a
> range() function that accepts a step argument is Python, and its behaviour
> is IMHO worse.
> For increasing ranges it requires a positive step, and if not just
> generates an empty range.
> For decreasing ranges it requires a negative step, and if not just
> generates an empty range (this applies even if using the default step value
> of 1 which is bonkers).
> 
> Making it a requirement to pass a negative step is definitely out of the
> question.
> Making it okay to use negative steps *only* for decreasing ranges could be
> sensible, but we check for the step parameter way before we look into the
> boundary values because those are different for int, float and string
> boundaries.
> Moreover, I personally find it weirder to require a sign for negative steps
> as for me a step is something that *must* be positive, and at least Kotlin
> seems to somewhat agree with me looking around at
> https://kotlinlang.org/docs/ranges.html#progression and playing with the
> source code
> Namely:
> for (i in 4 downTo 1 step 2) print(i)
> 
>> 42
> 
> for (i in 4 downTo 1 step -2) print(i)
> 
>> Exception in thread "main" java.lang.IllegalArgumentException: Step must
> be positive, was: -2.
> 
> 
>> - Values of '' or null in integer context (e.g. range(null, 10, 2)) should
>> IMHO emit a warning first, not directly be changed to a TypeError. The
>> usual BC / migration concern :-)
>>
> 
> When null is used, no TypeError is emitted, just the "usual" null to scalar
> deprecation that happens since
> https://wiki.php.net/rfc/deprecate_null_to_scalar_internal_arg got accepted.
> But I'll add an example to the RFC and a test case in the PR.
> 
> Trying to figure out if an empty string was used with another string
> boundary is tedious, as this information needs to somehow get carried
> around.
> A previous iteration of the PR used to convert empty strings to 0 with a
> warning, but considering the analysis I decide to just make this a
> ValueError as it doesn't seem that empty strings are actually used in
> practice.
> But this is an easy revert, and I'm not really bound to this decision.
> 
> Best regards,
> 
> George P. Banyard
> 

I like the RFC in general, just this negative $step parameter warning stood out 
to me.

While I agree that requiring a negative $step for a decreasing range is a bit 
silly,
I've always found it intuitive that a negative $step should be used for a 
decreasing range.
I'm not saying that it should be required, I'm just concerned about the BC 
break of emitting E_WARNING and breaking people's intuition.

The reasoning behind this is that range($start, $end, $step) (for me at least) 
has always been symmetric and consistent with a for loop:
  $array = [];
  for ($i = $start; $i < $end (or >); $i += $step) { $array[] = $i; }
So by allowing a negative step the behaviour is consistent with how for loops 
behave, and avoids a BC break.

That Kotlin doesn't require it makes sense for me because the words "down to" 
combined with a negative step indeed don't make sense.
The negativity is in a sense already embedded by explicitly writing "down to". 
It's less explicit for PHP's range function.

I looked at the source code of some of my projects and I do see some 
occurrences of range($high, $low, -1 (or another negative value)).

Just wanted to chime in quickly to state my thoughts on this.
Thanks.

Kind regards
Niels

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to