I think those are all good questions; there is another on my mind. share
in Combine was always a point of learning difficulty. Getting to that point was somewhat a struggle for those who think with an imperative mainframe. Not everyone has a modality of thinking that is functional. Share in my opinion was perhaps harder to grasp for some folks than even the initial hurdle between reference and value types (conceptually they have some overlaps). The question is: can we do better?
Is this problem something we can build tooling for that defines away that difficulty? This is why I favor the concept of the awaiting all clients to consume a value; more as an algorithm on an existing async sequence than say a channel-like thing. Because then we could perhaps inference the behavior via the type system.
For example:
extension AsyncSequence {
func goodNameGoesHere() -> (AsyncSideForABetterName<Self>, AsyncSideForABetterName <Self>)
}
The advantage via using a tuple return means that all of the sides MUST be used. The language enforces the concept of using all of the sides. If one is not used; it emits a warning. Obviously this is not the only way to solve it. That concept of leveraging the language to advance this feels more along the right path for at least part of the problem space. Perhaps in time we may find that there are more than just two or three solutions that deserve distinct representations.
From a material standpoint; autoconnect is almost NEVER used besides timer and multicast with Combine from my experience. In those cases it feels like a vestigial organ serving only a ritualistic "this is what you do" type usage. Which feels to me as perhaps something we want to avoid. Share is also rather mysterious for folks, the placement isn't immediately obvious to newcomers to Combine. I would like to avoid that mysteriousness.
P.S. To me multicast, share and such all make great sense to me, but I want to make sure we add things for their ease of use and utility and not "just because Combine did it".