-
-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add with_Completion
and with_Operation
variants that can return optional values
#4
base: main
Are you sure you want to change the base?
Conversation
Thank you! Ok, I think I see the problem you need to work around. Did you think about a parameter to allow/throw on nil? I haven't thought hard about this, but just wondering which API you think is most appropriate. |
I hadn't considered throwing as opposed to returning That makes me realize that some of my implementation could be simplified by catching only func withOptionalValueErrorCompletion(
/* ... */
) async throws -> Value? {
do {
return try await withValueErrorCompletion(isolation: isolation, function: function, body)
} catch ConnectionContinuationError.missingBothValueAndError {
return nil
}
} This responsibility could be delegated to package consumers, but would require exposing the error type and an extra The functions could also be renamed and be overloads for the originals, but would require a All that said, if the goal for the package is to provide just the essentials, I think making |
Ok, I completely agree with what you are saying. I guess I'm torn. Because on the one hand, is it even a good idea to throw on nil? It is a totally valid possible value, and the current API makes it impossible to return. I think it potentially quite convenient to have this system get rid of the optionals for you. But, that convenience now has a real cost in terms of API complexity. What do you think about something like this? public func withValueErrorCompletion<Service, Value: Sendable>(
isolation: isolated (any Actor)? = #isolation,
function: String = #function,
// a non-optional Value
_ body: (Service, sending @escaping (Value, Error?) -> Void) -> Void
) async throws -> Value {
// no more nil check for value here
} This now permits an optional generic, which I think will work for your case here? It would also shift responsibility to the What do you think about this? |
It's definitely desired to have optionals handled when they're not expected. I gave it a try and I don't think surfacing the optional handling to // service
class MyServiceImplementation: MyService {
func myFunction(reply: sending @escaping (Data?, Error?) -> Void) {
var success: Data?
var failure: Error?
do {
success = try someThrowingFunction()
} catch {
failure = error
}
reply(success, failure)
}
} // host
let data: Data = try await connection.withValueErrorCompletion { (service: MyService, completion: (Data, Error?) -> Void) in
service.myFunction { (success: Data?, failure: Error?) in
switch (success, failure) {
case let (_, failure?): completion(/* ??? */, failure)
case let (success?, nil): completion(success, nil)
case (nil, nil): completion(/* ??? */, MyError.unexpectedNil)
}
}
} This sure would be a lot easier if |
There are cases where a user may want to return an optional value and not throw an error.
This PR adds
NSXPCConnection.withOptionalValueErrorCompletion
and other relevant function variants that can return optional values.