Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

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

Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Tim Mackinnon
Hey guys - I’m wondering if someone might have a nice way of selecting the previous value in a list - but wrapping around to the last value if you are at the front.

Essentially I have an exercise with some values in a collection like:

list :=  #($a $e $o $u).

And I have an index into the list, and want to loop around from index 1, back to 4 when I hit the beginning of the list.

While moving forwards is pretty easy with mod - e.g.

^list at: (index \\ list size + 1)

I’m struggling with the cleanest way to do this backwards - as the following is unreadable to me (assuming index = 1)

^list at: (index - 2 \\ list size + 1)

And then I tried (which isn't bad - but still not quite right).

^list before: (list at: index) ifAbsent: [ids last].


I’m sure there is a better way to do this - but it’s alluding me?

Tim
       


Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

jgfoster
One of my recent assignments to first-year programming students was to model Left-Center-Right (https://en.wikipedia.org/wiki/LCR_(dice_game)) where they needed to do just what you are trying to do.

| size stream |
size := 10.
stream := WriteStream on: String new.
1 to: size do: [:i | 
stream
print: i; tab;
print: i \\ size + 1; tab;
print: i + size - 2 \\ size + 1; tab;
cr.
].
stream contents


On Mar 28, 2019, at 8:12 AM, Tim Mackinnon <[hidden email]> wrote:

Hey guys - I’m wondering if someone might have a nice way of selecting the previous value in a list - but wrapping around to the last value if you are at the front.

Essentially I have an exercise with some values in a collection like:

list :=  #($a $e $o $u).

And I have an index into the list, and want to loop around from index 1, back to 4 when I hit the beginning of the list.

While moving forwards is pretty easy with mod - e.g.

^list at: (index \\ list size + 1)

I’m struggling with the cleanest way to do this backwards - as the following is unreadable to me (assuming index = 1)

^list at: (index - 2 \\ list size + 1)

And then I tried (which isn't bad - but still not quite right).

^list before: (list at: index) ifAbsent: [ids last].


I’m sure there is a better way to do this - but it’s alluding me?

Tim





Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Peter Kenny
Tim

I found myself puzzling as to *why* James's solution works. This longer
explanation helped me to understand.

First, generalize moving forward to moving an arbitrary number of steps,
still with wrapping.

^list at: (index + move - 1 \\ size + 1

Second, realize that moving backward one step with wrapping is exactly
equivalent to moving forward (size - 1) steps - because of wrapping, a move
of size steps is null.

Finally, substitute move = size - 1.

^list at: (index + size - 2 \\ size + 1.

This can of course easily generalize to backward moves of any size.

HTH

Peter Kenny



--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Tim Mackinnon
Hey thanks guys - while it certainly makes sense when you think about it, I was kind of hoping we had something that was much more readable and obvious. It seems strange that when we have lots of esoteric things in collection, that something which is quite common to do isn’t there. I was kind of hoping we might have some circular list or something.

As it stands, if you really want to communicate this clearly you are almost better off just doing, the more obvious:

(Index := index - 1) = 0 ifTrue: [index := items size].

Anyway, an interesting one.

Tim

> On 28 Mar 2019, at 16:55, Peter Kenny <[hidden email]> wrote:
>
> Tim
>
> I found myself puzzling as to *why* James's solution works. This longer
> explanation helped me to understand.
>
> First, generalize moving forward to moving an arbitrary number of steps,
> still with wrapping.
>
> ^list at: (index + move - 1 \\ size + 1
>
> Second, realize that moving backward one step with wrapping is exactly
> equivalent to moving forward (size - 1) steps - because of wrapping, a move
> of size steps is null.
>
> Finally, substitute move = size - 1.
>
> ^list at: (index + size - 2 \\ size + 1.
>
> This can of course easily generalize to backward moves of any size.
>
> HTH
>
> Peter Kenny
>
>
>
> --
> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>


Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Peter Kenny
Tim

But the beauty of Smalltalk is that, if you need to use a particular
structure frequently, you can make it an object just by subclassing
something useful. In this case, you could create CircularList by subclassing
SequenceableCollection and re-implementing #before and #after (and maybe
tidying up #add if you don't want the circle to be extendable).

Pursuing this line of thought, we  already have one specialized subclass in
LinkedList. If the last element is linked to the first, this becomes
circular. I glanced at some of the methods to see how well this would work,
but because it regards links as separate from the linked objects, it got too
complicated. But it could give a starting point if you have lots of such
cases.

HTH

Peter Kenny


Tim Mackinnon wrote

> Hey thanks guys - while it certainly makes sense when you think about it,
> I was kind of hoping we had something that was much more readable and
> obvious. It seems strange that when we have lots of esoteric things in
> collection, that something which is quite common to do isn’t there. I was
> kind of hoping we might have some circular list or something.
>
> As it stands, if you really want to communicate this clearly you are
> almost better off just doing, the more obvious:
>
> (Index := index - 1) = 0 ifTrue: [index := items size].
>
> Anyway, an interesting one.
>
> Tim
>
>> On 28 Mar 2019, at 16:55, Peter Kenny &lt;

> peter@.co

> &gt; wrote:
>>
>> Tim
>>
>> I found myself puzzling as to *why* James's solution works. This longer
>> explanation helped me to understand.
>>
>> First, generalize moving forward to moving an arbitrary number of steps,
>> still with wrapping.
>>
>> ^list at: (index + move - 1 \\ size + 1
>>
>> Second, realize that moving backward one step with wrapping is exactly
>> equivalent to moving forward (size - 1) steps - because of wrapping, a
>> move
>> of size steps is null.
>>
>> Finally, substitute move = size - 1.
>>
>> ^list at: (index + size - 2 \\ size + 1.
>>
>> This can of course easily generalize to backward moves of any size.
>>
>> HTH
>>
>> Peter Kenny
>>
>>
>>
>> --
>> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>>





--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Tim Mackinnon
Hi Peter - yes of course you are right that its malleable, I guess I’m often suprised about the things we leave out and then discover weird things we’ve put in.

I had a quick look at LinkedList (I should have thought of that) - I might be able to do something with that (and this is now more out of curiosity) - but gosh its an easy way to crash your image. Having linked the first to the last, and then tried a quick: list after: $n - I’m now guessing I’m stuck in an infinite loop that even Cmd . won’t break out of!!!! ouch. 

Tim

On 29 Mar 2019, at 10:20, Peter Kenny <[hidden email]> wrote:

Tim

But the beauty of Smalltalk is that, if you need to use a particular
structure frequently, you can make it an object just by subclassing
something useful. In this case, you could create CircularList by subclassing
SequenceableCollection and re-implementing #before and #after (and maybe
tidying up #add if you don't want the circle to be extendable).

Pursuing this line of thought, we  already have one specialized subclass in
LinkedList. If the last element is linked to the first, this becomes
circular. I glanced at some of the methods to see how well this would work,
but because it regards links as separate from the linked objects, it got too
complicated. But it could give a starting point if you have lots of such
cases.

HTH

Peter Kenny


Tim Mackinnon wrote
Hey thanks guys - while it certainly makes sense when you think about it,
I was kind of hoping we had something that was much more readable and
obvious. It seems strange that when we have lots of esoteric things in
collection, that something which is quite common to do isn’t there. I was
kind of hoping we might have some circular list or something.

As it stands, if you really want to communicate this clearly you are
almost better off just doing, the more obvious:

(Index := index - 1) = 0 ifTrue: [index := items size].

Anyway, an interesting one.

Tim

On 28 Mar 2019, at 16:55, Peter Kenny &lt;

peter@.co

&gt; wrote:

Tim

I found myself puzzling as to *why* James's solution works. This longer
explanation helped me to understand.

First, generalize moving forward to moving an arbitrary number of steps,
still with wrapping.

^list at: (index + move - 1 \\ size + 1

Second, realize that moving backward one step with wrapping is exactly
equivalent to moving forward (size - 1) steps - because of wrapping, a
move
of size steps is null.

Finally, substitute move = size - 1.

^list at: (index + size - 2 \\ size + 1.

This can of course easily generalize to backward moves of any size.

HTH

Peter Kenny



--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html






--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Peter Kenny
Hi Tim. Sorry you crashed your image. I owe you an apology, because when I
looked at the code for LinkedList, I thought there was something odd, but I
dismissed it thinking ' they must have thought of that!' I think the problem
is that LinkedList inherits #after: from SequenceableCollection, meaning it
uses #atIndex: rather than following the links. Even so I don't see why it
loops; surely going outside the range of the index should be a known error
condition. Anyway, between us we may have discovered a bug in LinkedList. Do
you feel stirred up enough to raise it as an issue?

Peter


Tim Mackinnon wrote

> Hi Peter - yes of course you are right that its malleable, I guess I’m
> often suprised about the things we leave out and then discover weird
> things we’ve put in.
>
> I had a quick look at LinkedList (I should have thought of that) - I might
> be able to do something with that (and this is now more out of curiosity)
> - but gosh its an easy way to crash your image. Having linked the first to
> the last, and then tried a quick: list after: $n - I’m now guessing I’m
> stuck in an infinite loop that even Cmd . won’t break out of!!!! ouch.
>
> Tim
>
>> On 29 Mar 2019, at 10:20, Peter Kenny &lt;

> peter@.co

> &gt; wrote:
>>
>
>> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>> &lt;http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html&gt;





--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Tim Mackinnon
No problem Peter - I’ll raise a bug (as it happened, I had save my image a few hours before and epicea got back the few things I had changed since).

Rather strangely - even just trying to debug “myList next” (as in right click and pick debug it) seems to hang my image too (I didn’t expect that).

Tim

> On 29 Mar 2019, at 11:36, Peter Kenny <[hidden email]> wrote:
>
> Hi Tim. Sorry you crashed your image. I owe you an apology, because when I
> looked at the code for LinkedList, I thought there was something odd, but I
> dismissed it thinking ' they must have thought of that!' I think the problem
> is that LinkedList inherits #after: from SequenceableCollection, meaning it
> uses #atIndex: rather than following the links. Even so I don't see why it
> loops; surely going outside the range of the index should be a known error
> condition. Anyway, between us we may have discovered a bug in LinkedList. Do
> you feel stirred up enough to raise it as an issue?
>
> Peter
>
>
> Tim Mackinnon wrote
>> Hi Peter - yes of course you are right that its malleable, I guess I’m
>> often suprised about the things we leave out and then discover weird
>> things we’ve put in.
>>
>> I had a quick look at LinkedList (I should have thought of that) - I might
>> be able to do something with that (and this is now more out of curiosity)
>> - but gosh its an easy way to crash your image. Having linked the first to
>> the last, and then tried a quick: list after: $n - I’m now guessing I’m
>> stuck in an infinite loop that even Cmd . won’t break out of!!!! ouch.
>>
>> Tim
>>
>>> On 29 Mar 2019, at 10:20, Peter Kenny &lt;
>
>> peter@.co
>
>> &gt; wrote:
>>>
>>
>>> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>>> &lt;http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html&gt;
>
>
>
>
>
> --
> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>


Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Esteban A. Maringolo
In reply to this post by Peter Kenny
I would do it as an iterator (a circular one).
The structure of the underlying list is irrelevant here (as long as it is sequenceable), IMO.

Regards,

El vie., 29 de mar. de 2019 07:21, Peter Kenny <[hidden email]> escribió:
Tim

But the beauty of Smalltalk is that, if you need to use a particular
structure frequently, you can make it an object just by subclassing
something useful. In this case, you could create CircularList by subclassing
SequenceableCollection and re-implementing #before and #after (and maybe
tidying up #add if you don't want the circle to be extendable).

Pursuing this line of thought, we  already have one specialized subclass in
LinkedList. If the last element is linked to the first, this becomes
circular. I glanced at some of the methods to see how well this would work,
but because it regards links as separate from the linked objects, it got too
complicated. But it could give a starting point if you have lots of such
cases.

HTH

Peter Kenny


Tim Mackinnon wrote
> Hey thanks guys - while it certainly makes sense when you think about it,
> I was kind of hoping we had something that was much more readable and
> obvious. It seems strange that when we have lots of esoteric things in
> collection, that something which is quite common to do isn’t there. I was
> kind of hoping we might have some circular list or something.
>
> As it stands, if you really want to communicate this clearly you are
> almost better off just doing, the more obvious:
>
> (Index := index - 1) = 0 ifTrue: [index := items size].
>
> Anyway, an interesting one.
>
> Tim
>
>> On 28 Mar 2019, at 16:55, Peter Kenny &lt;

> peter@.co

> &gt; wrote:
>>
>> Tim
>>
>> I found myself puzzling as to *why* James's solution works. This longer
>> explanation helped me to understand.
>>
>> First, generalize moving forward to moving an arbitrary number of steps,
>> still with wrapping.
>>
>> ^list at: (index + move - 1 \\ size + 1
>>
>> Second, realize that moving backward one step with wrapping is exactly
>> equivalent to moving forward (size - 1) steps - because of wrapping, a
>> move
>> of size steps is null.
>>
>> Finally, substitute move = size - 1.
>>
>> ^list at: (index + size - 2 \\ size + 1.
>>
>> This can of course easily generalize to backward moves of any size.
>>
>> HTH
>>
>> Peter Kenny
>>
>>
>>
>> --
>> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>>





--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Ben Coman
In reply to this post by Tim Mackinnon


On Fri, 29 Mar 2019 at 18:57, Tim Mackinnon <[hidden email]> wrote:
Hi Peter - yes of course you are right that its malleable, I guess I’m often suprised about the things we leave out and then discover weird things we’ve put in.

I had a quick look at LinkedList (I should have thought of that) - I might be able to do something with that (and this is now more out of curiosity) - but gosh its an easy way to crash your image. Having linked the first to the last, and then tried a quick: list after: $n - I’m now guessing I’m stuck in an infinite loop that even Cmd . won’t break out of!!!! ouch. 

If you look at Hier(archy) of LinkList you'll see Semaphore underneath it.
I'm not sure, but there may be some VM magic around Semaphore and Process management that makes it fragile to changes.
I believe there have been some proposals to separate out the Process related LinkedList stuff, but I can't remember the exact arguments.

cheers -ben    
 

Tim

On 29 Mar 2019, at 10:20, Peter Kenny <[hidden email]> wrote:

Tim

But the beauty of Smalltalk is that, if you need to use a particular
structure frequently, you can make it an object just by subclassing
something useful. In this case, you could create CircularList by subclassing
SequenceableCollection and re-implementing #before and #after (and maybe
tidying up #add if you don't want the circle to be extendable).

Pursuing this line of thought, we  already have one specialized subclass in
LinkedList. If the last element is linked to the first, this becomes
circular. I glanced at some of the methods to see how well this would work,
but because it regards links as separate from the linked objects, it got too
complicated. But it could give a starting point if you have lots of such
cases.

HTH

Peter Kenny


Tim Mackinnon wrote
Hey thanks guys - while it certainly makes sense when you think about it,
I was kind of hoping we had something that was much more readable and
obvious. It seems strange that when we have lots of esoteric things in
collection, that something which is quite common to do isn’t there. I was
kind of hoping we might have some circular list or something.

As it stands, if you really want to communicate this clearly you are
almost better off just doing, the more obvious:

(Index := index - 1) = 0 ifTrue: [index := items size].

Anyway, an interesting one.

Tim

On 28 Mar 2019, at 16:55, Peter Kenny &lt;

peter@.co

&gt; wrote:

Tim

I found myself puzzling as to *why* James's solution works. This longer
explanation helped me to understand.

First, generalize moving forward to moving an arbitrary number of steps,
still with wrapping.

^list at: (index + move - 1 \\ size + 1

Second, realize that moving backward one step with wrapping is exactly
equivalent to moving forward (size - 1) steps - because of wrapping, a
move
of size steps is null.

Finally, substitute move = size - 1.

^list at: (index + size - 2 \\ size + 1.

This can of course easily generalize to backward moves of any size.

HTH

Peter Kenny



--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html






--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Marcus Denker-4


On 29 Mar 2019, at 14:24, Ben Coman <[hidden email]> wrote:



On Fri, 29 Mar 2019 at 18:57, Tim Mackinnon <[hidden email]> wrote:
Hi Peter - yes of course you are right that its malleable, I guess I’m often suprised about the things we leave out and then discover weird things we’ve put in.

I had a quick look at LinkedList (I should have thought of that) - I might be able to do something with that (and this is now more out of curiosity) - but gosh its an easy way to crash your image. Having linked the first to the last, and then tried a quick: list after: $n - I’m now guessing I’m stuck in an infinite loop that even Cmd . won’t break out of!!!! ouch. 

If you look at Hier(archy) of LinkList you'll see Semaphore underneath it.
I'm not sure, but there may be some VM magic around Semaphore and Process management that makes it fragile to changes.
I believe there have been some proposals to separate out the Process related LinkedList stuff, but I can't remember the exact arguments.

Yes, we did that… there is now ProcessList.

We ran into that problem far too often “hey, LinkedList can be cleaned up easily like this!” —> boom, everything broken.

Now we have ProcessList where it matters if code is changed to introduce a message send more and LinkedList where it does not.

Marcus
Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Peter Kenny
Tim

Going back to your original question, the answer is there all the time but
buried in the enormous method dictionaries of the Collection subclasses. If
you look at SequenceableCollection>>atWrap: you will see that it does
exactly what you want.

To get the item before the first, i.e. the zeroth:
#(1 2 3 4) atWrap: 0 => 4

To get the item after the last:
#(1 2 3 4) atWrap: 5 => 1

As seen here, the method is inherited by Array, so it should do all you
want.

HTH

Peter


Marcus Denker-4 wrote
>> On 29 Mar 2019, at 14:24, Ben Coman &lt;

> btc@

> &gt; wrote:
>>
>>
>>
>> On Fri, 29 Mar 2019 at 18:57, Tim Mackinnon &lt;

> tim@

> &gt; wrote:
>> Hi Peter - yes of course you are right that its malleable, I guess I’m
>> often suprised about the things we leave out and then discover weird
>> things we’ve put in.
>>
>> I had a quick look at LinkedList (I should have thought of that) - I
>> might be able to do something with that (and this is now more out of
>> curiosity) - but gosh its an easy way to crash your image. Having linked
>> the first to the last, and then tried a quick: list after: $n - I’m now
>> guessing I’m stuck in an infinite loop that even Cmd . won’t break out
>> of!!!! ouch.
>>
>> If you look at Hier(archy) of LinkList you'll see Semaphore underneath
>> it.
>> I'm not sure, but there may be some VM magic around Semaphore and Process
>> management that makes it fragile to changes.
>> I believe there have been some proposals to separate out the Process
>> related LinkedList stuff, but I can't remember the exact arguments.
>
> Yes, we did that… there is now ProcessList.
>
> We ran into that problem far too often “hey, LinkedList can be cleaned up
> easily like this!” —> boom, everything broken.
>
> Now we have ProcessList where it matters if code is changed to introduce a
> message send more and LinkedList where it does not.
>
> Marcus





--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Sven Van Caekenberghe-2
Haha, great discussion, great find. Amazing that all these things are just already there.

Pharo/Smalltalk programming is really 'studying the problem and the existing system, moving it to the desired state with as little work as possible' - including the use of frameworks and libraries.

> On 29 Mar 2019, at 18:08, Peter Kenny <[hidden email]> wrote:
>
> Tim
>
> Going back to your original question, the answer is there all the time but
> buried in the enormous method dictionaries of the Collection subclasses. If
> you look at SequenceableCollection>>atWrap: you will see that it does
> exactly what you want.
>
> To get the item before the first, i.e. the zeroth:
> #(1 2 3 4) atWrap: 0 => 4
>
> To get the item after the last:
> #(1 2 3 4) atWrap: 5 => 1
>
> As seen here, the method is inherited by Array, so it should do all you
> want.
>
> HTH
>
> Peter
>
>
> Marcus Denker-4 wrote
>>> On 29 Mar 2019, at 14:24, Ben Coman &lt;
>
>> btc@
>
>> &gt; wrote:
>>>
>>>
>>>
>>> On Fri, 29 Mar 2019 at 18:57, Tim Mackinnon &lt;
>
>> tim@
>
>> &gt; wrote:
>>> Hi Peter - yes of course you are right that its malleable, I guess I’m
>>> often suprised about the things we leave out and then discover weird
>>> things we’ve put in.
>>>
>>> I had a quick look at LinkedList (I should have thought of that) - I
>>> might be able to do something with that (and this is now more out of
>>> curiosity) - but gosh its an easy way to crash your image. Having linked
>>> the first to the last, and then tried a quick: list after: $n - I’m now
>>> guessing I’m stuck in an infinite loop that even Cmd . won’t break out
>>> of!!!! ouch.
>>>
>>> If you look at Hier(archy) of LinkList you'll see Semaphore underneath
>>> it.
>>> I'm not sure, but there may be some VM magic around Semaphore and Process
>>> management that makes it fragile to changes.
>>> I believe there have been some proposals to separate out the Process
>>> related LinkedList stuff, but I can't remember the exact arguments.
>>
>> Yes, we did that… there is now ProcessList.
>>
>> We ran into that problem far too often “hey, LinkedList can be cleaned up
>> easily like this!” —> boom, everything broken.
>>
>> Now we have ProcessList where it matters if code is changed to introduce a
>> message send more and LinkedList where it does not.
>>
>> Marcus
>
>
>
>
>
> --
> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html


Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Tim Mackinnon
Peter - nice spot. I’m glad we kept this thread running as I keep learning more of the nooks and crannies.

I keep finding that between odd naming (although in this case I’m shocked I missed that one - I need to get better at using spotter) and unfortunate method categorisation, that I struggle to find these gems.

If I searched for “wrap”, can I do it over a hierarchy? I need to try that, as this would eliminate prefix ordering.



Tim

Sent from my iPhone

> On 29 Mar 2019, at 17:28, Sven Van Caekenberghe <[hidden email]> wrote:
>
> Haha, great discussion, great find. Amazing that all these things are just already there.
>
> Pharo/Smalltalk programming is really 'studying the problem and the existing system, moving it to the desired state with as little work as possible' - including the use of frameworks and libraries.
>
>> On 29 Mar 2019, at 18:08, Peter Kenny <[hidden email]> wrote:
>>
>> Tim
>>
>> Going back to your original question, the answer is there all the time but
>> buried in the enormous method dictionaries of the Collection subclasses. If
>> you look at SequenceableCollection>>atWrap: you will see that it does
>> exactly what you want.
>>
>> To get the item before the first, i.e. the zeroth:
>> #(1 2 3 4) atWrap: 0 => 4
>>
>> To get the item after the last:
>> #(1 2 3 4) atWrap: 5 => 1
>>
>> As seen here, the method is inherited by Array, so it should do all you
>> want.
>>
>> HTH
>>
>> Peter
>>
>>
>> Marcus Denker-4 wrote
>>>> On 29 Mar 2019, at 14:24, Ben Coman &lt;
>>
>>> btc@
>>
>>> &gt; wrote:
>>>>
>>>>
>>>>
>>>> On Fri, 29 Mar 2019 at 18:57, Tim Mackinnon &lt;
>>
>>> tim@
>>
>>> &gt; wrote:
>>>> Hi Peter - yes of course you are right that its malleable, I guess I’m
>>>> often suprised about the things we leave out and then discover weird
>>>> things we’ve put in.
>>>>
>>>> I had a quick look at LinkedList (I should have thought of that) - I
>>>> might be able to do something with that (and this is now more out of
>>>> curiosity) - but gosh its an easy way to crash your image. Having linked
>>>> the first to the last, and then tried a quick: list after: $n - I’m now
>>>> guessing I’m stuck in an infinite loop that even Cmd . won’t break out
>>>> of!!!! ouch.
>>>>
>>>> If you look at Hier(archy) of LinkList you'll see Semaphore underneath
>>>> it.
>>>> I'm not sure, but there may be some VM magic around Semaphore and Process
>>>> management that makes it fragile to changes.
>>>> I believe there have been some proposals to separate out the Process
>>>> related LinkedList stuff, but I can't remember the exact arguments.
>>>
>>> Yes, we did that… there is now ProcessList.
>>>
>>> We ran into that problem far too often “hey, LinkedList can be cleaned up
>>> easily like this!” —> boom, everything broken.
>>>
>>> Now we have ProcessList where it matters if code is changed to introduce a
>>> message send more and LinkedList where it does not.
>>>
>>>    Marcus
>>
>>
>>
>>
>>
>> --
>> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Peter Kenny
We could probably mine this forever to get interesting connections, but I
shall restrict myself to three (and then shut up).
a. The code for SequenceableCollection>>atWrap: is a single line, which
exactly reproduces Tim's original method. Maybe a hint for programming
strategy - if code is mysterious, encapsulate it in a method with an
informative name.
b. Modulo reduction to achieve wrapping just works with zero-based indexing.
The -1 and +1 can be seen as temporarily converting to zero-based indexing
and then converting back.
c. If you think of backward shifting more than one place, you end up with a
negative index. This works equally well (I checked!), but it is not obvious
that it must, because it is not obvious that <negativeInteger> \\
<positiveInteger> has to be positive - I have encountered systems with a
different convention.
HTH

Peter Kenny


Tim Mackinnon wrote

> Peter - nice spot. I’m glad we kept this thread running as I keep learning
> more of the nooks and crannies.
>
> I keep finding that between odd naming (although in this case I’m shocked
> I missed that one - I need to get better at using spotter) and unfortunate
> method categorisation, that I struggle to find these gems.
>
> If I searched for “wrap”, can I do it over a hierarchy? I need to try
> that, as this would eliminate prefix ordering.
>
>
>
> Tim
>
> Sent from my iPhone
>
>> On 29 Mar 2019, at 17:28, Sven Van Caekenberghe &lt;

> sven@

> &gt; wrote:
>>
>> Haha, great discussion, great find. Amazing that all these things are
>> just already there.
>>
>> Pharo/Smalltalk programming is really 'studying the problem and the
>> existing system, moving it to the desired state with as little work as
>> possible' - including the use of frameworks and libraries.
>>
>>> On 29 Mar 2019, at 18:08, Peter Kenny &lt;

> peter@.co

> &gt; wrote:
>>>
>>> Tim
>>>
>>> Going back to your original question, the answer is there all the time
>>> but
>>> buried in the enormous method dictionaries of the Collection subclasses.
>>> If
>>> you look at SequenceableCollection>>atWrap: you will see that it does
>>> exactly what you want.
>>>
>>> To get the item before the first, i.e. the zeroth:
>>> #(1 2 3 4) atWrap: 0 => 4
>>>
>>> To get the item after the last:
>>> #(1 2 3 4) atWrap: 5 => 1
>>>
>>> As seen here, the method is inherited by Array, so it should do all you
>>> want.
>>>
>>> HTH
>>>
>>> Peter
>>>
>
>>> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>>
>>





--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Ben Coman
In reply to this post by Peter Kenny


On Sat, 30 Mar 2019 at 01:09, Peter Kenny <[hidden email]> wrote:
Tim

Going back to your original question, the answer is there all the time but
buried in the enormous method dictionaries of the Collection subclasses.

And we have Tools > Finder > Examples >  #(10 20 30 40) . 5 . 10  
to help unbury such methods... 
      
 
If
you look at SequenceableCollection>>atWrap: you will see that it does
exactly what you want.

To get the item before the first, i.e. the zeroth:
#(1 2 3 4) atWrap: 0 => 4

To get the item after the last:
#(1 2 3 4) atWrap: 5 => 1

As seen here, the method is inherited by Array, so it should do all you
want.

HTH

Peter



--------------- 

Marcus Denker-4 wrote
>> On 29 Mar 2019, at 14:24, Ben Coman &lt;
>> I believe there have been some proposals to separate out the Process
>> related LinkedList stuff, but I can't remember the exact arguments.
>
> Yes, we did that… there is now ProcessList.
>
> We ran into that problem far too often “hey, LinkedList can be cleaned up
> easily like this!” —> boom, everything broken.
>
> Now we have ProcessList where it matters if code is changed to introduce a
> message send more and LinkedList where it does not.
 
Cool !!

cheers -ben
Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Richard O'Keefe
In reply to this post by Tim Mackinnon
As you noted, wrapping going forward:
 seq at: index \\ seq size + 1
Wrapping going backward is nearly as easy:
 seq at: (index - 2) \\ seq size + 1
This would not work with #rem:

On Fri, 29 Mar 2019 at 04:13, Tim Mackinnon <[hidden email]> wrote:
Hey guys - I’m wondering if someone might have a nice way of selecting the previous value in a list - but wrapping around to the last value if you are at the front.

Essentially I have an exercise with some values in a collection like:

list :=  #($a $e $o $u).

And I have an index into the list, and want to loop around from index 1, back to 4 when I hit the beginning of the list.

While moving forwards is pretty easy with mod - e.g.

^list at: (index \\ list size + 1)

I’m struggling with the cleanest way to do this backwards - as the following is unreadable to me (assuming index = 1)

^list at: (index - 2 \\ list size + 1)

And then I tried (which isn't bad - but still not quite right).

^list before: (list at: index) ifAbsent: [ids last].


I’m sure there is a better way to do this - but it’s alluding me?

Tim



Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Richard O'Keefe
In reply to this post by jgfoster
This loop is a special case.
size := 10.
prevIndex := size. prevValue := seq at: prevIndex.
thisIndex := 1.    thisValue := seq at: thisIndex.
nextIndex := 2.    nextIndex := seq at: nextIndex.
[thisIndex <= size] whileTrue: [
  ...
  prevIndex := thisIndex. prevValue := thisValue.
  thisIndex := nextIndex. thisValue := nextValue.
  nextIndex := nextIndex = size
                 ifTrue:  [1]
                 ifFalse: [nextIndex + 1].
  nextValue := seq at: nextIndex].
Counting backwards is similar.
 

On Fri, 29 Mar 2019 at 04:44, James Foster <[hidden email]> wrote:
One of my recent assignments to first-year programming students was to model Left-Center-Right (https://en.wikipedia.org/wiki/LCR_(dice_game)) where they needed to do just what you are trying to do.

| size stream |
size := 10.
stream := WriteStream on: String new.
1 to: size do: [:i | 
stream
print: i; tab;
print: i \\ size + 1; tab;
print: i + size - 2 \\ size + 1; tab;
cr.
].
stream contents


On Mar 28, 2019, at 8:12 AM, Tim Mackinnon <[hidden email]> wrote:

Hey guys - I’m wondering if someone might have a nice way of selecting the previous value in a list - but wrapping around to the last value if you are at the front.

Essentially I have an exercise with some values in a collection like:

list :=  #($a $e $o $u).

And I have an index into the list, and want to loop around from index 1, back to 4 when I hit the beginning of the list.

While moving forwards is pretty easy with mod - e.g.

^list at: (index \\ list size + 1)

I’m struggling with the cleanest way to do this backwards - as the following is unreadable to me (assuming index = 1)

^list at: (index - 2 \\ list size + 1)

And then I tried (which isn't bad - but still not quite right).

^list before: (list at: index) ifAbsent: [ids last].


I’m sure there is a better way to do this - but it’s alluding me?

Tim





Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Richard O'Keefe
In reply to this post by Tim Mackinnon
If a Smalltalk system did have a "cyclic" indexing
method that did "self at: (index - 1) \\ self size + 1",
where would it be?
Since it makes sense for all and only sequences,
we'd expect it to be in SequenceableCollection.
Since it is like #at:, and #at: is an 'accessing'
method, we'd expect to find it in the 'accessing'
methods of SequenceableCollection.
And indeed, #atWrap:[put:] are exactly where
they ought to be.
SequenceableCollection selectorsInCategory: 'accessing'
=> #(#after: #after:ifAbsent: #allButFirst #allButFirst: #allButLast #allButLast: #anyOne #at:ifAbsent: #at:incrementBy: #atAll: #atAll:put: #atAll:putAll: #atAllPut: #atLast: #atLast:ifAbsent: #atLast:put: #atPin: #atWrap: #atWrap:put: #before: #before:ifAbsent: #eighth #fifth #first #first: #fourth #from:to:put: #identityIndexOf: #identityIndexOf:ifAbsent: #indexOf: #indexOf:ifAbsent: #indexOf:startingAt: #indexOf:startingAt:ifAbsent: #indexOfAnyOf: #indexOfAnyOf:ifAbsent: #indexOfAnyOf:startingAt: #indexOfAnyOf:startingAt:ifAbsent: #indexOfSubCollection:startingAt: #indexOfSubCollection:startingAt:ifAbsent: #integerAt: #integerAt:put: #last #last: #lastIndexOf: #lastIndexOf:ifAbsent: #lastIndexOf:startingAt:ifAbsent: #lastIndexOfAnyOf:startingAt:ifAbsent: #middle #ninth #replaceAll:with: #replaceFrom:to:with: #replaceFrom:to:with:startingAt: #second #seventh #sixth #size #swap:with: #third)

On Fri, 29 Mar 2019 at 22:31, Tim Mackinnon <[hidden email]> wrote:
Hey thanks guys - while it certainly makes sense when you think about it, I was kind of hoping we had something that was much more readable and obvious. It seems strange that when we have lots of esoteric things in collection, that something which is quite common to do isn’t there. I was kind of hoping we might have some circular list or something.

As it stands, if you really want to communicate this clearly you are almost better off just doing, the more obvious:

(Index := index - 1) = 0 ifTrue: [index := items size].

Anyway, an interesting one.

Tim

> On 28 Mar 2019, at 16:55, Peter Kenny <[hidden email]> wrote:
>
> Tim
>
> I found myself puzzling as to *why* James's solution works. This longer
> explanation helped me to understand.
>
> First, generalize moving forward to moving an arbitrary number of steps,
> still with wrapping.
>
> ^list at: (index + move - 1 \\ size + 1
>
> Second, realize that moving backward one step with wrapping is exactly
> equivalent to moving forward (size - 1) steps - because of wrapping, a move
> of size steps is null.
>
> Finally, substitute move = size - 1.
>
> ^list at: (index + size - 2 \\ size + 1.
>
> This can of course easily generalize to backward moves of any size.
>
> HTH
>
> Peter Kenny
>
>
>
> --
> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>


Reply | Threaded
Open this post in threaded view
|

Re: Easiest way to wrap around the indexed value in a list (mod doesn't quite work)

Peter Kenny
In reply to this post by Ben Coman
Ben

Thanks for pointing this out - I was not aware of it. At first sight the
notation is completely opaque - I had no idea what the query in you post
meant until I read through the instructions in Finder. Now I have tried it,
it looks quite handy.

Minor nit-pick: The instructions say the components of a example are
separated by a period. This should read 'period plus space'; I put in #(1 2
3 4).0.4 as an example and it said no such method. Granted the example
quoted in the instructions has spaces, but a lazy so-and-so like me can be
guaranteed to foul it up.

Peter


Ben Coman wrote
> On Sat, 30 Mar 2019 at 01:09, Peter Kenny &lt;

> peter@.co

> &gt; wrote:
>
>> Tim
>>
>> Going back to your original question, the answer is there all the time
>> but
>> buried in the enormous method dictionaries of the Collection subclasses.
>
>
> And we have Tools > Finder > Examples >  #(10 20 30 40) . 5 . 10
> to help unbury such methods...
>
>
>
>> If
>> you look at SequenceableCollection>>atWrap: you will see that it does
>> exactly what you want.
>>
>> To get the item before the first, i.e. the zeroth:
>> #(1 2 3 4) atWrap: 0 => 4
>>
>> To get the item after the last:
>> #(1 2 3 4) atWrap: 5 => 1
>>
>> As seen here, the method is inherited by Array, so it should do all you
>> want.
>>
>> HTH
>>
>> Peter
>>
>>
>
> ---------------
>
>>
>> Marcus Denker-4 wrote
>> >> On 29 Mar 2019, at 14:24, Ben Coman &lt;
>> >> I believe there have been some proposals to separate out the Process
>> >> related LinkedList stuff, but I can't remember the exact arguments.
>> >
>> > Yes, we did that… there is now ProcessList.
>> >
>> > We ran into that problem far too often “hey, LinkedList can be cleaned
>> up
>> > easily like this!” —> boom, everything broken.
>> >
>> > Now we have ProcessList where it matters if code is changed to
>> introduce
>> a
>> > message send more and LinkedList where it does not.
>>
>
> Cool !!
>
> cheers -ben





--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

12