[OT] Programming language WATs

H. S. Teoh hsteoh at quickfur.ath.cx
Mon Feb 6 23:01:06 PST 2012

On Mon, Feb 06, 2012 at 10:02:15PM -0800, Jonathan M Davis wrote:
> On Monday, February 06, 2012 21:49:23 H. S. Teoh wrote: 
> In my experience, most C++ programmers ignore streams for basic I/O,
> if not in general. They're nice for some basic stuff and for object
> oriented stuff, but as soon as you need formatting, they're a pain.
> So, for the most part, printf gets used. I think that about the only
> place that I see streams used much is binary streams which take
> advantage of an object knowing how to write and read itself to and and
> from a stream. But even that's rare in my experience. I'm sure that it
> depends on the programmers though.

I don't see what's the discrepancy between formatting and streams. As
far as I'm concerned, writeln() is essentially taking a bunch of
objects, converting them to string representations, and writing said
strings sequentially to some output channel (i.e., output stream).

> You end up with pretty much the same thing in C# and Java. println and
> its friends are what's used most frequently (though it works better in
> D, C#, and Java than it does in C++, thanks to toString), though
> streams do get used for some stuff - usually not text though. It
> probably varies a bit from programmer to programmer though.

And println/writeln is essentially writing to an output stream. It can
be a file, a socket, a pipe, whatever. The functionality of a stream is
all that's needed to implement it.

> Regardless, I wouldn't really consider a file to be specific to either
> the stdio approach or streams. If anything, I find it bizarre that
> std.stream uses the term File for a stream. That seems to me to be
> like making a container into a range or an iterator, which really
> doesn't make sense. You have a range _over_ a container, not a
> container which is a range. One of the reasons that dealing with
> dynamic arrays in D can be so confusing is that they're ranges and
> people think that they're containers (though they really aren't, since
> they don't own their memory). Mixing the concept of file and stream
> seems like a bad idea. But it's probably just a case of a poorly named
> type.

To me, most file operations are essentially treating them as streams.
Reading a text file, whether it's char by char or line by line, is
essentially reading from an input stream. The program then does some
processing, and writes out some other data, be it text or binary or
whatever, but it's mostly just a series of sequential writes. So it's an
output stream.

Of course, files have more operations than just I/O streams; sometimes
you do need seeking to some offset, and read/write stuff in
non-sequential order. But usually this entails very specific file
structures (e.g., using B-trees for databases, etc.). Most of the time
it's just stream in, stream out.

The advantage of using streams is that your code can then operate on
more than just files. It can work with sockets and pipes (that cannot
support random access), string buffers, procedural data generators and
consumers, etc.. Files are just a small subset of what the code can
actually be used for.

In my mind, the D I/O system ought to be designed around this general
concept. Files are just a specific instance of a stream (or range or
what-have-you) that happens to have random-access operations, just as
arrays just happen to be ranges with random-access operations, but
ranges cover so much more.

In fact, functions like writeln() really ought to be completely generic
as to where the output is sent. One should be able to, for example,
write to a char buffer, or even to a char consumer function or object.
Similarly, things like readln() or byLine() should be able to work with
anything that behaves like a sequential source of characters: console,
files, sockets, strings, functions or objects that spit out chars, etc..
Couple this with buffers (which are themselves sources/sinks, that just
happen to have random-access for a limited range), and you've pretty
much covered 90% of what files are generally used for.

The other 10% involve complicated file structures that will require
hand-coding anyway, so it is sufficient for the actual File class to
have extra methods for random access, and the user can code up the rest.

Code that need just a data source and/or a data sink shouldn't need to
be unnecessarily limited to files. Imagine if std.regex can work
directly with files. Or sockets. With no additional code save opening
the file/setting up the socket. Or procedurally generated strings,
without needing any intermediate buffers.

> In any case, std.stream is rather old and outdated and will be
> replaced at some point with a range-based API. And its replacement may
> interact with std.stdio better.

Yikes! So I should just avoid using it altogether then? How come it's
not marked deprecated?


Which is worse: ignorance or apathy? Who knows? Who cares? -- Erich Schubert

More information about the Digitalmars-d mailing list