Yeah, I definitely see your point that nil is also the idiomatic way to indicate a sequence end, and so it would be kinda odd to reinvent the wheel on that front for this API alone.
I'm kind of ambivalent as to what exactly the 'right' shape for the value-driven termination version of this API isâI haven't thought about it enough to have strong opinions. A well-established pattern throughout the language is to pass a metatype value for disambiguation when necessary, so perhaps that would work here? I.e., Observed would offer the following two initializers:
// Some details/annotations omitted for brevity
public init(_ emit: () throws(Failure) -> Element)
public init(_ type: Element.Type, _ emit: () throws(Failure) -> Element?)
So that the 'intentionally-terminate-when-optional` case could be written:
let pageURLStream = Observed(URL.self) { [weak webPage] webPage?.currentURL }
and for the non-optional version you'd write:
let pageHostStream = Observed { webPage.currentURL.host }
as desired, which would not terminate on String?.none because Element == String?.
After writing it out, this modification still isn't quite satisfying to me, though, due to the monadic nature of optional chaining. E.g., with the above code for the pageURLStream, if WebPage later changed its currentURL property to be of type URL?, we still wouldn't get a compilation failure, and a webPage going away entirely would be treated the same as the URL (perhaps temporarily!) becoming nil.
So I think there may be good reasons here to require a totally 'out-of-band' method for signaling sequence termination separately from "value became nil". I realize this puts a damper on the 'happy path' for easy observation of weak reference properties, though. 