This is a tiny refinement to the std lib that to provide a convenience member on Result when when Success is Void.
Result types with a success type of Void are commonly used when no further information about the result of the operation are required – other than to know it was successful. In these cases, it is necessary to return a Result via Result.success(()).
The double parentheses can sometimes become an impediment to legibility – especially if wrapped within another set of parentheses, e.g. as an argument within a function call.
someHandler(.success(()))
I propose a tiny addition to the std-lib to iron out the kink:
extension Result where Success == Void {
public static var success: Result { .success(()) }
}
Which smoothes out the above example to:
someHandler(.success)
Whilst I can't think of elsewhere in the Swift std-lib where this kind of specialisation of types with Void type arguments exists, there is prior history elsewhere in the Apple eco-system. Specifically Combine's PassthroughSubject.send() which presumably added the syntactic sugar to clean-up the SwiftUI api.
Often it makes sense for your API to consistently return Results over chopping and changing between Optionals and Results. That's because Results are composable with flatMap, etc.
In lieu of an addition to the standard library, why not use the spelling that's preferred in Swift: .success(Void)? This is not the only circumstance in which ()-as-Void is less than readable, and it's precisely for that reason that Void is preferred.
+1 I have been reaching for .success(()) personally when facing this. One of my coworkers prefers the more verbose .success(Void()). I would prefer to just use this extension instead. I might even consider adding this extension in the meantime.
extension Result where Success == Void {
public static func success() -> Self { .success(()) }
}
Which hopefully is still a big improvement on ergonomics/legibility.
someHandler(.success())
Side note: maybe there is eventually room for a more wide-ranging, complex proposal: any function with Void parameters would have a counterpart function generated where the default ()s are specified/provided.
e.g. with Combine's PassthroughSubject.send(_:), this would automatically derive PassthroughSubject.send() when PassthroughSubject's Output type is Void. For enums, it would automatically generate the appropriate counterpart static var (as described above for Result.) Of course, if a user-defined equivalent already exists – that would take precedence.
This is a pretty common issue with generics and PATs, and can be hard to work around; I’d really like to see a language-level solution if one is feasible.
One way to think of it would be that for value parameters of a generic/associated type that resolve to Void, there should be a synthesized default value of ().
What's the issue with having .success ambiguous without any type context?
i.e. can you provide an example that twists the programmer's arm while coding, in order to favor .success() over .success?
I just found this thread a year later because I ran into this issue myself. Did anything ever come of this idea? I'm also curious about the answer to @ronyfadel `s question.
I don't know if it's because the compiler got more advanced, but all the examples you posted don't emit a compilation error, at least not on Xcode 14.2.
Is there any other ambiguity caused by declaring .success without parenthesis?