I use the approach you mention, restoring stream position, in my ParrotTalk code, both in Pharo and in Java. I am not peeking more than one character but I had to implement peek in Java and your code example is how I did this code.


- HH


On Thu, Nov 2, 2017 at 04:59, Prof. Andrew P. Black <black@cs.pdx.edu> wrote:
I sometimes find, when working with a stream, that I need to "peek ahead" a few items, without disturbing the state of the stream. The message stream peek gives me the next item, but doesn���t generalize to multiple items,   So I end up writing code like this:

    findSomething
| savedPosition result |
savedPosition := stream position.
stream position: start.
"code involving various manipulations of stream, including stream next"
result := stream position + 1.
stream position: savedPosition.
^ result

This code involves at least two temps, is not very easy to read, and risks not resetting the stream properly if I do a return.

It seems to me that a better solution would be what Kent Beck calls an "execute around" method:

    findSomething
^ stream unchangedDuring: [ :s |
"code involving various manipulations of stream, including stream next"
stream position + 1 ]

I���m not sure that I like the name #unchangedDuring:; perhaps you can think of a better one? 

The  implementation of this would be

PositionableStream >> #unchangedDuring: aBlock
"execute aBlock with self as argument. Ensure that when this method returns,
I still have my current state."
| savedPosition |
savedPosition := self position.
^ [ aBlock value: self ] ensure: [ self position: savedPosition ]

or perhaps

PositionableStream >> #unchangedDuring: aBlock
"execute aBlock with self as argument. Ensure that when this method returns,
I still have my current state."

^ [ aBlock value: self copy ]

which might be better in the case that the stream is a file stream and aBlock causes the buffer to be refreshed from the disk.

  • Do other Smalltalks have a method like this?  
  • Does it already exist in Pharo, somewhere that I���ve failed to look? 
  • Would it be a worthwhile addition to Pharo?  
  • What would be a good name?