A brief rant on naming: Combine's "sink" operator

This post is ranty but hopefully taken in the in the spirit in which it's intended, which is mostly in jest. But I really do seek to clarify the reasoning behind the use of the term "sink" for subscribing to publishers.

When we name things, we often use terms that intuitively convey an abstraction. I assume that's what "sink" is intended to do, but I can't for the life of me figure it out. I can't even figure out if it's intended to be a noun or a verb.

Like a lot of people, I often look at code examples to figure things out. Most operator names make perfect sense, and I can infer what they're doing. But when I see sink, the last thing I think of is "Oh, that's where the actual subscription occurs." It almost seems like an intentional obfuscation. It might as well be called banana.

So I watch videos on combine, and the narrator nonchalantly mentions that we subscribe to publishers by calling sink (naturally!), as if it's a totally obvious name for such an operation. Am I crazy? Is everyone else crazy?

Seriously though, I suspect the name has some reasonable origin, and the actual purpose of this post is to figure that out. If the answer is something like "the term was originally used in a research paper written in the early nineties first detailing the FRP approach..." I'll be a bit disappointed that it managed to make its way into the public API.

8 Likes

The stream goes down the sink.

7 Likes

“Source” and “sink” are established names from graph theory (Flow network - Wikipedia). I agree that it’s not an everyday use of the word “sink”, though, or at least it’s a stretch.

16 Likes

In engineering generally, where there are flows (of anything: heat, data, water, etc.) the terms ‘source’ and ‘sink’ are commonly used to refer to locations where whatever is flowing (respectively) starts out / is produced and ends up / is consumed. So heat flows from its source toward a heat sink, water flows down a (kitchen?) sink, and Combine reactive streams flow toward a .sink(receiveValue:).

18 Likes

It's the same etymology as “heat sink” and “time sink”.

1 Like

I appreciate the explanation! @jrose as well.

It feels perhaps too couched in obscure academic lingo, especially considering there's no shortage of more intuitive alternative names, but now that I'm in on the secret I feel much better.

4 Likes

I wondered where the term sink came from too. I guess the explanations make sense.

What makes it harder to understand is that everything previous in the chain is an action, referred to with a verb (map, filter, decode, etc), and in this context the verb “sink” makes little sense. It’s far too late now, but drain would have probably been more obvious and makes sense both as a noun (stream goes to the drain) and as a verb (it drains the stream).

2 Likes

If you want to embrace the weird and wacky in Combine, I don't think it's necessary to go further than subscribe(), which is in the Publisher protocol, not the Subscriber protocol.

So subscribers don't subscribe, but publishers do subscribe subscribers, at which point reason has totally left the building.

The hilarity doesn't end there, though. Publishers that sink also subscribe subscribers, so I suppose they subscribe subscribers to sinks, or possibly sink to subscribers, or maybe they sink subscribers in … sinks.

The reason things are named like this is that they're all terms of art, which means that "everyone knows" what they mean, and can't possibly be confused. :stuck_out_tongue_winking_eye:

11 Likes

It’s a bit unfortunate that Combine mixed up some terms, but yeah Sink is „well known” for „end of stream” elements.

It is, in my opinion, simpler to understand if such names come in pairs, as then one explains it as: stream flows from source to sink. This is why in Akka Streams we designed it as three main types of operators by thr way: Sources (origin of stream / data, like a file array or timer) + Flows (anything in between, e.g. operators) + Sinks (terminal operators, like fold or „write to file” etc.)

This is another reason why, personally, I still think the „AsyncStream” which is under SE review right now should be renamed, as it is exactly a Source, and definitely not a middle piece, nor a terminal piece. We’ll see if others agree though.

11 Likes

I always read it as a verb in the sense "To move or be moved into something.". You are moving (sinking) the result of the stream into whatever closure you pass to sink. e.g., you map it, then decode it, then filter it, then sink it.

1 Like

Thank you. I wasted hours trying to figure this out a year ago and this thread is the first time I’ve ever seen “sink” explained. Every bit of documentation and every article, tutorial, etc, completely skipped over explaining why an apparently unrelated word was used there, as if were so obvious that it didn’t need to be mentioned (or as if they were too embarrassed to admit they didn’t know the reason).
Words have meaning. Some words have many meanings. We need to be precise about these things.

2 Likes

To me, the Combine API was designed for authors of publisher and subscribers, instead of consumers of publishers. The vast majority of Combine users are consumers, not authors.

Consumers want to subscribe to publishers. The documentation is littered with the "subscribe" word. We even have subscribe(on:options:) that controls when subscription of some upstream publisher happens.

This very frequent use case is performed with... sink.

On the other side, authors want to create subscriptions so that their publishers can start dumping values down to their subscribers.

This very rare use case is performed with... subscribe.

Let's just take this story as a design lesson: when you design an API, design for the most frequent use case of your expected users first. Not YOUR most frequent use case of your own API. And let's forgive the Combine authors, who authored a lot of publishers and subscribers. After a while, sink just... sinks in :wink:

11 Likes

Sink is fairly explanatory. Other naming conventions in combine are odd. Cancellable what exactly.

Just to add a data point, I first encountered “sink” while working in the home automation industry. When setting up a home A/V system, you’d use our software to build a graph of some sources (DVD player, cable box) through some receivers or mixers or whatever, and finally into some sinks (speakers, TVs, projectors). I think the metaphor of “pipeline goes down the drain of the sink” was used at the time to explain it to me, although I had originally heard it before I saw it written, and thought the word was “sync,” which somehow made more sense to me.

Agree that the wording is weird, and that “subscribe” or “receive” or “produce” or something along those lines would do a better job of aligning the actual meaning with common word usage. But it’s unlikely to change in Combine any time soon, so it’s mostly academic.

2 Likes