Experience with Java taught me to loath ethe "do I/O by composing lots of little wrappers" approach for several reasons: - the fact that the commonest case was not the default case, so that simple obvious code was somewhere between disgracefully slow and wrong - the extra complexity needed to get it right (having to know a plethora of wrapper classes instead of just getting sensible defaults) - the poor performance.
In my own Smalltalk system I hewed to the ANSI Smalltalk standard and if you do FileStream read: aFileName or FileStream write: aFileName you get a text file using the encoding set by your environment's locale, the native line ending convention, Simple, easy, and leaves Java's I/O performance in the dust. Of course wrappers are available for the rare cases when you need them, but you don't _have_ to use them. One reason this matters is that there are two ways to write a stream: s2 := WrapperClass on: s1 -- closing s2 just closes s2, not s1. s2 := WrapperClass onOwn: s1 -- closing s2 closes s1 as well And yes, both of these *are* used. On 24 June 2018 at 04:53, Sven Van Caekenberghe <s...@stfx.eu> wrote: > Peter, > > > On 23 Jun 2018, at 15:39, Peter Uhnák <i.uh...@gmail.com> wrote: > > > > Hi, > > > > I'm starting to familiarize myself with new streams, and one thing I've > noticed is the removal of #lineEndConvention (which I use all the time). > > > > So a statement like this > > > > aFile writeStreamDo: [ :stream | > > stream lineEndConvention: #lf. > > stream << '...' > > ]. > > > > has to be written like so > > > > aFile writeStreamDo: [ :rawStream | |stream| > > stream := (ZnNewLineWriterStream on: rawStream) forLf. > > stream << '...' > > ]. > > > > which feels very messy because I am mixing writing with the > configuration. And I don't even take account for buffered/encoded > decorators. Plus it increases the incidental complexity -- I need another > variable, and I can accidentally write to the wrong stream, etc. > > > > Would a method like #writeStream:do: (or #writeStreamTransform:do:) make > sense? E.g. > > > > aFile writeStreamTransform: [ :stream | (ZnNewLineWriterStream on: > stream) ] do: [ :stream | > > stream << '...' > > ] > > > > To separate the composition from the usage? > > > > Thanks, > > Peter > > The goals of the 'new' (they have existed for quite a while) streams is to > go from single big complex do all classes and replace that with a > composition of much simpler single purpose classes. Another goal is to > reduce the API so that it becomes easier to create new stream classes. Of > course, a consequence is that you need composition to get the functionality > you want. But I think you understand the tradeoff. > > If the mixing of configuration/setup with writing/reading bothers you, > then I would suggest using two methods. One that does only the > writing/reading assuming a limited API, and another that does the > configuration/setup, using composition. > > Note that the streams that you get already are a composition (most often a > BinaryFileStream wrapped in a Buffered stream wrapped in a > Encoding/Decoding stream). EOL translation is not a standard part of that. > But there is quite some system code that does uses EOL translation. > > Sven > > > >