Interval form: x to: y when x > y - or how to count down...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Interval form: x to: y when x > y - or how to count down...

Tim Mackinnon
I've just been caught out with Intervals - why can't you do:
5 to: 1 do: [ :i | Transcript show: i printString]  (eg a negative interval)?

if you want to iterate down a series of numbers do you really have to do:
5 to: 1 by: -1 do: […

I always assumed that if x > y the step was automatically -1 (but its not).

I asked on Discord - and someone pointed out that if you use variables it could be ambiguous - but is it really? I don’t know if other smalltalks do it this way (I vaguely recall Dolphin going down, but not sure).

Either way the Interval comment should mention this - and I’ll correct it when I get the wisdom of the crowd here.

Tim
Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

khinsen
On 22/02/2019 15:57, Tim Mackinnon wrote:
> I've just been caught out with Intervals - why can't you do:
> 5 to: 1 do: [ :i | Transcript show: i printString]  (eg a negative interval)?
>
> if you want to iterate down a series of numbers do you really have to do:
> 5 to: 1 by: -1 do: […
>
> I always assumed that if x > y the step was automatically -1 (but its not).

Expectations are obviously personal, but as far as I am concerned, I'd
expect to see the behavior that Pharo implements. If you don't specify
by:, you get a default value of 1. That's much simpler than a default
value depending on the bounds of the interval.

Konrad.


Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

Tim Mackinnon
If it’s always been that way - and things rely on it, sure.

But it doesn’t feel like the Smalltalk way to me.

Having to know about adding -1 seems very C, whereas Smalltalk always seems more natural ... and 5 to: 1 seems like you would count down, not be an empty range and do nothing.

But as you say, it’s personal. I’m still curious though.

Tim

Sent from my iPhone

> On 22 Feb 2019, at 16:13, Konrad Hinsen <[hidden email]> wrote:
>
>> On 22/02/2019 15:57, Tim Mackinnon wrote:
>> I've just been caught out with Intervals - why can't you do:
>> 5 to: 1 do: [ :i | Transcript show: i printString]  (eg a negative interval)?
>>
>> if you want to iterate down a series of numbers do you really have to do:
>> 5 to: 1 by: -1 do: […
>>
>> I always assumed that if x > y the step was automatically -1 (but its not).
>
> Expectations are obviously personal, but as far as I am concerned, I'd expect to see the behavior that Pharo implements. If you don't specify by:, you get a default value of 1. That's much simpler than a default value depending on the bounds of the interval.
>
> Konrad.
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

Sven Van Caekenberghe-2


> On 22 Feb 2019, at 22:35, Tim Mackinnon <[hidden email]> wrote:
>
> If it’s always been that way - and things rely on it, sure.
>
> But it doesn’t feel like the Smalltalk way to me.
>
> Having to know about adding -1 seems very C, whereas Smalltalk always seems more natural ... and 5 to: 1 seems like you would count down, not be an empty range and do nothing.
>
> But as you say, it’s personal. I’m still curious though.

I personally would find it cool if

 10 to: 1

counted down, it feels natural. But I must say I haven't thought it through.

I do known that Interval is a class that leads to lots of discussions and disagreements.

> Tim
>
> Sent from my iPhone
>
>> On 22 Feb 2019, at 16:13, Konrad Hinsen <[hidden email]> wrote:
>>
>>> On 22/02/2019 15:57, Tim Mackinnon wrote:
>>> I've just been caught out with Intervals - why can't you do:
>>> 5 to: 1 do: [ :i | Transcript show: i printString]  (eg a negative interval)?
>>>
>>> if you want to iterate down a series of numbers do you really have to do:
>>> 5 to: 1 by: -1 do: […
>>>
>>> I always assumed that if x > y the step was automatically -1 (but its not).
>>
>> Expectations are obviously personal, but as far as I am concerned, I'd expect to see the behavior that Pharo implements. If you don't specify by:, you get a default value of 1. That's much simpler than a default value depending on the bounds of the interval.
>>
>> Konrad.
>>
>>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

Offray Vladimir Luna Cárdenas-2

On 22/2/19 16:57, Sven Van Caekenberghe wrote:

>
>> On 22 Feb 2019, at 22:35, Tim Mackinnon <[hidden email]> wrote:
>>
>> If it’s always been that way - and things rely on it, sure.
>>
>> But it doesn’t feel like the Smalltalk way to me.
>>
>> Having to know about adding -1 seems very C, whereas Smalltalk always seems more natural ... and 5 to: 1 seems like you would count down, not be an empty range and do nothing.
>>
>> But as you say, it’s personal. I’m still curious though.
> I personally would find it cool if
>
>  10 to: 1
>
> counted down, it feels natural. But I must say I haven't thought it through.
>
> I do known that Interval is a class that leads to lots of discussions and disagreements.
>
I agree with Tim and Sven: "bigger to: smaller" should count backwards,
if we think in the way we used on a day to day expectation.

Cheers,

Offray


Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

Richard O'Keefe
In reply to this post by Tim Mackinnon
Of the couple of hundred programming languages I have
used, there is precisely one that does what you expect
(the S programming language, as implemented in R).
And it is a major pain in the posterior with no upside
that I can discern.

Suppose I want a sequence of n consecutive integers
beginning with 1.  In Smalltalk, (1 to: n) does the
job.  In R, 1:n *almost* does the job.  But what
happens when n = 0?  Smalltalk gives me the right
answer: an empty sequence.  R gives me (1,0).  That
means that *every* *flaming* *time* I write
for (i in 1:n) {...}
I have to take special care to ensure that n is not
0, sometimes even having to whack in an extra
if (n > 0) for (i in 1:n) {...}

Trawling through my Smalltalk code, I find that about
 6.8% of my counted loops are by: -1,
 0.7% of them are by: a negative number other than -1,
 2.5% of them are by: a positive number other than 1,
90  % are just to:do: with no by:
Inspecting some of the 90% showed that many of them
would go catastrophically wrong if 1 to: 0 do:
performed its body

On Sat, 23 Feb 2019 at 03:58, Tim Mackinnon <[hidden email]> wrote:
I've just been caught out with Intervals - why can't you do:
5 to: 1 do: [ :i | Transcript show: i printString]  (eg a negative interval)?

if you want to iterate down a series of numbers do you really have to do:
5 to: 1 by: -1 do: […

I always assumed that if x > y the step was automatically -1 (but its not).

I asked on Discord - and someone pointed out that if you use variables it could be ambiguous - but is it really? I don’t know if other smalltalks do it this way (I vaguely recall Dolphin going down, but not sure).

Either way the Interval comment should mention this - and I’ll correct it when I get the wisdom of the crowd here.

Tim
Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

Tim Mackinnon
Hi Richard - but why would you expect 1 to: 0 to give you an empty sequence?

If I inspect “0 to: 1” I see:
1 -> 0
2 -> 1

So I would expect “1 to: 0” to see:
1 -> 1
2 -> 0.

I asked for a sequence going from 1 down to 0 (in my mind).  Knowing about all the by: -1 stuff seems very C’ish.

Of course, I get that maybe it will break peoples existing code (and maybe that would be why it never gets changed) - but it still feels very strange. Or am I missing something?

Tim

On 28 Feb 2019, at 12:38, Richard O'Keefe <[hidden email]> wrote:

Of the couple of hundred programming languages I have
used, there is precisely one that does what you expect
(the S programming language, as implemented in R).
And it is a major pain in the posterior with no upside
that I can discern.

Suppose I want a sequence of n consecutive integers
beginning with 1.  In Smalltalk, (1 to: n) does the
job.  In R, 1:n *almost* does the job.  But what
happens when n = 0?  Smalltalk gives me the right
answer: an empty sequence.  R gives me (1,0).  That
means that *every* *flaming* *time* I write
for (i in 1:n) {...}
I have to take special care to ensure that n is not
0, sometimes even having to whack in an extra
if (n > 0) for (i in 1:n) {...}

Trawling through my Smalltalk code, I find that about
 6.8% of my counted loops are by: -1,
 0.7% of them are by: a negative number other than -1,
 2.5% of them are by: a positive number other than 1,
90  % are just to:do: with no by:
Inspecting some of the 90% showed that many of them
would go catastrophically wrong if 1 to: 0 do:
performed its body

On Sat, 23 Feb 2019 at 03:58, Tim Mackinnon <[hidden email]> wrote:
I've just been caught out with Intervals - why can't you do:
5 to: 1 do: [ :i | Transcript show: i printString]  (eg a negative interval)?

if you want to iterate down a series of numbers do you really have to do:
5 to: 1 by: -1 do: […

I always assumed that if x > y the step was automatically -1 (but its not).

I asked on Discord - and someone pointed out that if you use variables it could be ambiguous - but is it really? I don’t know if other smalltalks do it this way (I vaguely recall Dolphin going down, but not sure).

Either way the Interval comment should mention this - and I’ll correct it when I get the wisdom of the crowd here.

Tim

Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

Richard O'Keefe
I would expect 1:0 to give me an empty sequence
because (a) for all other natural numbers n,
1:n gives me a sequence of n numbers, and (b)
how else am I supposed to get an empty sequence?
Under your interpretation, (x to: y) would never
be empty.

This has absolutely nothing to do with C.
As I commented, every programming language I
know except S uses a default increment of +1
in counted loops, if it allows default increments
at all.  Fortran, Algol 68, Pascal, PL/I, the
seq(1) command in Unix, Haskell, the `seq'
function in Erlang, between/3 in Prolog, OCaml,
F#, InterLISP-D, and so it goes.

Fortran is an interesting case, because Fortran 66
left DO label id = lower,upper
unspecified when lower > upper and several compilers
made such loops execute once, to the point where
programmer tended to think the standard required that,
but Fortran 77 nailed it down: NO iterations in that
case.

Here's a typical use of #to:do:
   s := 0.
   1 to: a size do: [:i |
     a at: i put: (s := (a at: i) + s)].
Why would you think it a good idea for this
to crash if the array is empty?

Smalltalk being Smalltalk, nothing stops you adding

  through: end do: aBlock
    self to: end by: (end < self ifTrue: [-1] ifFalse: [1])
                 do: aBlock.

to Integer if you really want to.

Oh, there's an ambiguity.  Should
5 through 1 mean 5,4,3,2,1 or 1,2,3,4,5?
Both can be argued for.


On Fri, 1 Mar 2019 at 02:03, Tim Mackinnon <[hidden email]> wrote:
Hi Richard - but why would you expect 1 to: 0 to give you an empty sequence?

If I inspect “0 to: 1” I see:
1 -> 0
2 -> 1

So I would expect “1 to: 0” to see:
1 -> 1
2 -> 0.

I asked for a sequence going from 1 down to 0 (in my mind).  Knowing about all the by: -1 stuff seems very C’ish.

Of course, I get that maybe it will break peoples existing code (and maybe that would be why it never gets changed) - but it still feels very strange. Or am I missing something?

Tim

On 28 Feb 2019, at 12:38, Richard O'Keefe <[hidden email]> wrote:

Of the couple of hundred programming languages I have
used, there is precisely one that does what you expect
(the S programming language, as implemented in R).
And it is a major pain in the posterior with no upside
that I can discern.

Suppose I want a sequence of n consecutive integers
beginning with 1.  In Smalltalk, (1 to: n) does the
job.  In R, 1:n *almost* does the job.  But what
happens when n = 0?  Smalltalk gives me the right
answer: an empty sequence.  R gives me (1,0).  That
means that *every* *flaming* *time* I write
for (i in 1:n) {...}
I have to take special care to ensure that n is not
0, sometimes even having to whack in an extra
if (n > 0) for (i in 1:n) {...}

Trawling through my Smalltalk code, I find that about
 6.8% of my counted loops are by: -1,
 0.7% of them are by: a negative number other than -1,
 2.5% of them are by: a positive number other than 1,
90  % are just to:do: with no by:
Inspecting some of the 90% showed that many of them
would go catastrophically wrong if 1 to: 0 do:
performed its body

On Sat, 23 Feb 2019 at 03:58, Tim Mackinnon <[hidden email]> wrote:
I've just been caught out with Intervals - why can't you do:
5 to: 1 do: [ :i | Transcript show: i printString]  (eg a negative interval)?

if you want to iterate down a series of numbers do you really have to do:
5 to: 1 by: -1 do: […

I always assumed that if x > y the step was automatically -1 (but its not).

I asked on Discord - and someone pointed out that if you use variables it could be ambiguous - but is it really? I don’t know if other smalltalks do it this way (I vaguely recall Dolphin going down, but not sure).

Either way the Interval comment should mention this - and I’ll correct it when I get the wisdom of the crowd here.

Tim

Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

K K Subbu
In reply to this post by Tim Mackinnon
On 28/02/19 6:33 PM, Tim Mackinnon wrote:
>
> So I would expect “1 to: 0” to see:
> 1 -> 1
> 2 -> 0.

It is difficult for code to guess the intent of the coder. Did the coder
intend an decreasing sequence or a stopping condition (i == end or i >
end?). Perhaps, we could use an explicit selector:

   5 downto: 1

to disambiguate between the two cases.

Regards .. Subbu

Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

Tim Mackinnon
Actually thats quite a good suggestion - it probably should have been:

#upTo:
#downTo:
#to:by:

In the first place (but I’m guessing this change will never happen)



> On 1 Mar 2019, at 05:35, K K Subbu <[hidden email]> wrote:
>
> On 28/02/19 6:33 PM, Tim Mackinnon wrote:
>> So I would expect “1 to: 0” to see:
>> 1 -> 1
>> 2 -> 0.
>
> It is difficult for code to guess the intent of the coder. Did the coder intend an decreasing sequence or a stopping condition (i == end or i > end?). Perhaps, we could use an explicit selector:
>
>  5 downto: 1
>
> to disambiguate between the two cases.
>
> Regards .. Subbu
>


Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

Sven Van Caekenberghe-2


> On 1 Mar 2019, at 12:22, Tim Mackinnon <[hidden email]> wrote:
>
> Actually thats quite a good suggestion - it probably should have been:
>
> #upTo:
> #downTo:
> #to:by:
>
> In the first place (but I’m guessing this change will never happen)

I like this too.

Why would this not happen ? It is just one selector more.

I think the only possible issue is that #to:do: is known by the compiler, which makes it faster than any other iteration, even do: - there is always a tradeoff between readability and raw speed.

>> On 1 Mar 2019, at 05:35, K K Subbu <[hidden email]> wrote:
>>
>> On 28/02/19 6:33 PM, Tim Mackinnon wrote:
>>> So I would expect “1 to: 0” to see:
>>> 1 -> 1
>>> 2 -> 0.
>>
>> It is difficult for code to guess the intent of the coder. Did the coder intend an decreasing sequence or a stopping condition (i == end or i > end?). Perhaps, we could use an explicit selector:
>>
>> 5 downto: 1
>>
>> to disambiguate between the two cases.
>>
>> Regards .. Subbu
>>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

K K Subbu
On 01/03/19 5:35 PM, Sven Van Caekenberghe wrote:
> I like this too.
>
> Why would this not happen ? It is just one selector more.
>
> I think the only possible issue is that #to:do: is known by the
> compiler, which makes it faster than any other iteration, even do: -
> there is always a tradeoff between readability and raw speed.

Thank you for the kind words. I am not sure if speed would be affected
much by:

downTo: stop
     ^self to: stop by: -1

downTo: stop do: aBlock
     ^self to: stop by: -1 do: aBlock

In performance critical paths, one can always use to:do: with explicit
steps.

Regards .. Subbu

Reply | Threaded
Open this post in threaded view
|

Re: Interval form: x to: y when x > y - or how to count down...

Tim Mackinnon
Hey - sometimes these more philosophical conversations do amount to something. I will propose to gene changes and submit a pr - as after all, Pharo is ours and pointing someone to #downTo: or #upTo: would be very rewarding (and for Richard - #to: would remain the same so everyone wins)

Tim

Sent from my iPhone



Sent from my iPhone

>> On 1 Mar 2019, at 18:30, K K Subbu <[hidden email]> wrote:
>>
>> On 01/03/19 5:35 PM, Sven Van Caekenberghe wrote:
>> I like this too.
>> Why would this not happen ? It is just one selector more.
>> I think the only possible issue is that #to:do: is known by the
>> compiler, which makes it faster than any other iteration, even do: -
>> there is always a tradeoff between readability and raw speed.
>
> Thank you for the kind words. I am not sure if speed would be affected much by:
>
> downTo: stop
>   ^self to: stop by: -1
>
> downTo: stop do: aBlock
>   ^self to: stop by: -1 do: aBlock
>
> In performance critical paths, one can always use to:do: with explicit steps.
>
> Regards .. Subbu
>