Peeking at a stream

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

Peeking at a stream

Prof. Andrew P. Black
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?



Reply | Threaded
Open this post in threaded view
|

Re: Peeking at a stream

Guillermo Polito
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:
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?






--

   

Guille Polito

Research Engineer

Centre de Recherche en Informatique, Signal et Automatique de Lille

CRIStAL - UMR 9189

French National Center for Scientific Research - http://www.cnrs.fr


Web: http://guillep.github.io

Phone: +33 06 52 70 66 13

Reply | Threaded
Open this post in threaded view
|

Re: Peeking at a stream

henry
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


On Thu, Nov 2, 2017 at 04:59, Prof. Andrew P. Black <black@...> 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?



Reply | Threaded
Open this post in threaded view
|

Re: Peeking at a stream

Denis Kudriashov
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]>:
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?




Reply | Threaded
Open this post in threaded view
|

Re: Peeking at a stream

aglynn42
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]
Sent: Thursday, November 2, 2017 5:00 AM
To: [hidden email]
Subject: [Pharo-users] Peeking at a stream

 

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?

 

 

 

 

Reply | Threaded
Open this post in threaded view
|

Re: Peeking at a stream

Ben Coman


On Thu, Nov 2, 2017 at 9:28 PM, Andrew Glynn <[hidden email]> wrote:

Perhaps #keepStateWhile or something similar might be better than #unchangedDuring ?


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

From: [hidden email]
Sent: Thursday, November 2, 2017 5:00 AM
To: [hidden email]
Subject: [Pharo-users] Peeking at a stream

 

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?

 

 

 

 


Reply | Threaded
Open this post in threaded view
|

Re: Peeking at a stream

henry
In reply to this post by aglynn42
How about #peekAhead?

- HH


-------- Original Message --------
Subject: Re: [Pharo-users] Peeking at a stream
Local Time: November 2, 2017 9:28 AM
UTC Time: November 2, 2017 1:28 PM
To: Any question about pharo is welcome <[hidden email]>

Perhaps #keepStateWhile or something similar might be better than #unchangedDuring ?

 

Sent from Mail for Windows 10

 

Sent: Thursday, November 2, 2017 5:00 AM
Subject: [Pharo-users] Peeking at a stream

 

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?

 

 

 

 


Reply | Threaded
Open this post in threaded view
|

Re: Peeking at a stream

Prof. Andrew P. Black
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




Reply | Threaded
Open this post in threaded view
|

Re: Peeking at a stream

Guillermo Polito
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:

> 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







--

   

Guille Polito

Research Engineer

Centre de Recherche en Informatique, Signal et Automatique de Lille

CRIStAL - UMR 9189

French National Center for Scientific Research - http://www.cnrs.fr


Web: http://guillep.github.io

Phone: +33 06 52 70 66 13