[Pitch] `Never` as the parameter type for function that does not take a parameter

This works well for a verb (i.e. something that historically has () after it) but not for other parts of speech/concepts which, over time, lose their vestigial parens.

There's still one more level of syntactical nothingness to eliminate in those cases, e.g.

extension Result where Success == Void {
  static var success: Self { .success(()) }
}

That's a pain nowadays not only because of having to write the overloads (and deal with any compilation speed hits), but also the inconsistency of the compiler's interpretation of them:

// In most contexts, this `result` is now `.success(())`
let result = Result<_, Error>.success

// And you can get the one that nobody probably wants with explicit typing.
let makeResult = Result<_, Error>.success as (()) -> _

// But hereā€¦
extension Result where Success == Void {
  static func voidSuccessContext() {
    // Currently, "Ambiguous use of 'success'", without explicit typing to `Self`.
    let result = success
  }
}

I don't think variadic generics address this?

if we arenā€™t already committed to the ā€œarity and labels are part of the nameā€ model, we should commit to it now, otherwise documentation tooling maintainers are in for a world of painā€¦

This seems like the sort of pitch that is Never going to get much traction..

(ba dum tiss)

5 Likes

I feel you may not have passed an argument there.

/groan

2 Likes

It may be both useful and make sense. Maybe it also fits some logic. But that's besides the point: It is impossible to use Never for this use case today, because Never already have a difference, non-compatible meaning. Changing its semantics would break the existing semantics.

If this is indeed deemed useful, a new type would need to be invented. Maybe Nothing or something like that. Feel free to suggest and bike shed names.

But Never is never going to get repurposed as proposed.

3 Likes

If SE-0347 gets accepted we could perhaps also use default arguments?

struct PassthroughSubject<Output> {
  func send(_ output: Output = ())
}
2 Likes

That was my initial understanding of SE-0347 initially. Then I changed my mind.

Changed your mind, in the sense that you consider a function definition like that to be harmful, or at least bad practice? Or you changed your mind, in the sense that you no longer think such a function definition should compile under SE-0347?

As I tried to explain in the linked comment, I think that using SE-0347 in order to solve this kind of problem is ill-advised.

To say it in another way: it is not because you find ONE type that is a possible default, that you found THE type that is designed to be the default (the real use case of SE-0347).

In my Void/Ping example, using SE-0347 would have a different outcomes, depending on it is Void, or Ping, that is the first type that is identified as a sensible default. If the evolution of code has Ping appear first, then SE-0347 would use Ping. If the evolution of the same code has Void appear first, then SE-0347 would use Void. To me, this is the sign that SE-0347 was improperly used in this case. Void is not designed to be the default type. It just happens that one developer was first to think that Void would be a good default. This developer was just lucky. In reality he's squatting SE-0347, he's using an undue convenience.

Thanks. Then I did understand you correctly :-)

2 Likes