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.
|
Hi Andrew, My first hunch is that you don't want to change PositionableStream. Because it works on collections and files (because of inheritance). But not on other kind of streams that are not part of the hierarchy, such as sockets. And we are cleaning that part. Instead, some time ago Sven produced a really nice hierarchy of stream decorators. Check the package: Zinc-Character-Encoding-Core There you have ZnBufferedReadStream That implements buffering in an orthogonal way. Maybe it makes more sense to put such method there? Guille On Thu, Nov 2, 2017 at 9:59 AM, Prof. Andrew P. Black <[hidden email]> wrote:
|
In reply to this post by Prof. Andrew P. Black
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
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: |
In reply to this post by Prof. Andrew P. Black
Hi. In XStreams this method called #explore: . 2017-11-02 9:59 GMT+01:00 Prof. Andrew P. Black <[hidden email]>:
|
In reply to this post by Prof. Andrew P. Black
Perhaps #keepStateWhile or something similar might be better than #unchangedDuring ? Sent from Mail for Windows 10 From: [hidden email] 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. ^ 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. or perhaps PositionableStream >> #unchangedDuring: aBlock I still have my current state." 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.
|
On Thu, Nov 2, 2017 at 9:28 PM, Andrew Glynn <[hidden email]> wrote:
Something like "keepState" was also my first impression, but "During" seems to be the convention for restoring things after a code block completes. Are there methods breaking that convention? cheers -ben
|
In reply to this post by aglynn42
How about #peekAhead? - HH
|
In reply to this post by Guillermo Polito
> On 2 Nov 2017, at 10:10 , Guillermo Polito <[hidden email]> wrote: > > My first hunch is that you don't want to change PositionableStream. Because it works on collections and files (because of inheritance). But not on other kind of streams that are not part of the hierarchy, such as sockets. And we are cleaning that part. > > Instead, some time ago Sven produced a really nice hierarchy of stream decorators. Check the package: > > Zinc-Character-Encoding-Core > > There you have > > ZnBufferedReadStream > > That implements buffering in an orthogonal way. Maybe it makes more sense to put such method there? > I wanted this to be something light-weight. I really don’t want to have to wrap my stream in a decorator before peeking ahead. Because I’m doing this in SmaCC, I implemented #explore: (that’s the name I chose) in SmaCCLineNumberStream. But I think that the general solution is to put this method in a Trait, so that it can be combined into any stream, whether or not that stream inherits from PositionableStream. There are probably other methods that could go in such a trait too. Actually, the idea of resetting a stream to a prior position is much less general, and easier to implement, then general positionability. Over the weekend I posted an issue that discusses positioning a MultiButeFileStream — that’s a good example. Here is my implementation — really simple. ``` explore: aBlock "evaluate aBlock with this stream as argument. When done, reset my position to the current position." | savedPosition | savedPosition := self position. [ ^ aBlock value: self ] ensure: [ self position: savedPosition ] ``` Andrew |
Yeah, I understand. The thing is that we will remove in the near future MultiByteFileStream. And not all streams have conceptually a position. Today there was a mail from Sven about that. On Mon, Nov 13, 2017 at 2:48 PM, Prof. Andrew P. Black <[hidden email]> wrote:
|
Free forum by Nabble | Edit this page |