What happened to the proposed source/sink semantics in IO?

It’s a connector to PostGres DBMS (md5 auth) machine

Why is flush() even on the interface? Recipients of the interface have no reason to perform a flush. They shouldn’t even be aware that the stream is buffered. From their perspective, if write() didn’t error out then the data is in the stream. Their concern does not extend beyond the interface. To flush the stream, you’d call flush() on the stream.

From what I can gather, flush() is on the interface because the interface is being as a base class for the purpose of code reuse. Different writers would basically inherit the ability to flush by having std.Io.Writer as a field. Programmers would just have to do a dynamic_cast manually to get to the parent class.

What you called “the problem of stream.writer().write()” stems from exactly this arrangement. Why would you be reaching for the interface after all, if the interface exists ostensibly to facilitate the use of different streams? You have the stream already. You know its type. You know what it can do. Why use the interface? Because it’s not an merely interface. It’s a superclass. The write functionality is implemented there. This is inheritance by stealth.

2 Likes

Because you need it for certain things.

Let’s say you write an SMTP client implementation. There you go and send a line to the server, wait for the response, check the response, and do it quite multiple times for a single email (and then there is the communication overhead for the client<->server connection itself).
In between every step you HAVE to flush the buffer since you only get an answer AFTER the server got your line.

If the interface wouldn’t have a flush operation, you couldn’t use the Writer/Reader interfaces but you would need to operate on the socket directly, which does not just make testing harder, but also creates a hard dependency.

Here an example from an exercise sheet I once got at my university of how this might look:

220 faui03.informatik.uni-erlangen.de ESMTP Postfix
HELO faui06j.informatik.uni-erlangen.de
250 faui03.informatik.uni-erlangen.de
MAIL FROM:<be15piel@cip.cs.fau.de>
250 2.1.0 Ok
RCPT TO:<hansdampf@example.org>
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
From: Max Mustermann <be15piel@cip.cs.fau.de>
To: <hansdampf@example.org>
Subject: Hallo Hans
Dies ist der Body der Mail. Auch hier werden Zeilen mit \r\n getrennt.
..Diese Zeile beginnt in der Eingabe mit nur einem Punkt.
.
250 2.0.0 Ok: queued as 65AC33E9A9
QUIT
221 2.0.0 Bye

The lines which begin with a number are the answers from the server.

Ah, you’re actually bringing up a point that I’d made before somewhere else. If you’re writing an SMTP client, why would you want to use a generic read/write interface? It’s not like you program is going to be reading SMTP commands from a file or a piped output from another program. Only an actual network connection would make sense in this scenario. Yet you thought it’s natural to use a generic interface.

That’s the result of what I call the “power of the name”. Concepts with names attached to them just stand out much more in our minds than nameless alternatives. The lack of a word precludes the idea represented by that word.

SMTP is more of a stand in for a protocol with this behaviour (another could be any protocol which does a 3-way handshake in the beginning), but why shouldn’t you be able to go through a pipe or a hardware interface like a serial connection? SMTP is after all a well understood protocol with quite a few implementations.

1 Like

Personally I hate the sink analogy and would prefer pretty much any other naming. To me a sink is where I wash off dirt to hopefully never see it again and I never really flush my sinks in daily use.

If I had to find a real life analogy it would probably be a conveyerbelt but that fails the buffering. So I would recommend to name it what it really is a “data transfer”.

Now we have an abstract without any breaking analogies. And since it’s abstract we have multiple options for flush. I like “complete”.

try transfer.complete();

That works for me buffered and unbuffered. It has a source and a destination.

1 Like

can go through a tunnel or a proxy. People like to insert all kinds of weird stuff in between Alice and Bob.

2 Likes

Also, for testing / simulation purposes.

2 Likes

I don’t think conveyor belt is necessarily bad, people like to say that coding is a bit like Factorio, but sink is already used in audio engineering, mechanical engineering, chemical engineering, and many other engineering and physics fields to (successfuly) convey flow of data. The sink in your room is actually named after the physics concept of a sink and not vice versa.

1 Like

And the etymology of the word goes back more than a thousand years only a handful of definitions is about preservation of something as opposed to loosing/getting rid of something.

I can work with source, but I dislike the term sink for this purpose.

std.Io.Reader and Writer aren’t specific to ‘loading’ and ‘saving’ data (to some disk or longer-term storage), to the best of my understanding. They’re more generally for moving data in from elsewhere (Reader/Source) and out to elsewhere (Writer/Sink). If we go with this more generalized, not file-specific interpretation of the interface’s purpose, the semantics of “loosing” (sending) something is also fitting.

1 Like