Git Product home page Git Product logo

Comments (15)

anpol avatar anpol commented on June 20, 2024

Actually, I'm not sure that failable initializers is the best approach. I suspect most users are expecting that most GCD calls succeed, so they will use unwrapped values without checking for nil.

Probably, it would be better to provide an error handler that would be invoked when libdispatch call returns NULL. Such error handler could be set by the user, its possible behavior could be either assert/fail (this is the default), or log message, or ignore error completely. If the error is ignored, than we can fallback to failable initializer when feasible, or use non-failable initializer otherwise.

With an error handler, failable initializers can be safely defined as "init!" which would preserve compatibility and likely annoy users as little as possible.

from dispatchkit.

ElvishJerricco avatar ElvishJerricco commented on June 20, 2024

While I agree that implicitly unwrapped failable initializers would be the right choice, I'm not sure if an error handler is the way to go about it. What would the error handler really do?

from dispatchkit.

anpol avatar anpol commented on June 20, 2024

Default error handler could call assertionFailure() or preconditionFailure(). Another error handler could do nothing and allow control flow to proceed to failable initializer.

from dispatchkit.

anpol avatar anpol commented on June 20, 2024

One possible way to illustrate this:

typealias ErrorHandler = (String, StaticString, UInt) -> Void
var errorHandler: ErrorHandler = defaultErrorHandler

func defaultErrorHandler(message: String, file: StaticString, line: UInt) {
    preconditionFailure(message, file: file, line: line)
}

func invokeErrorHandler(message: String, file: StaticString = __FILE__, line: UInt = __LINE__) {
    errorHandler(message, file, line)
}

func dispatch_api_example() -> Int? { return nil }

struct Wrapper {
    let value: Int

    init!() {
        if let result = dispatch_api_example() {
            self.value = result
        } else {
            invokeErrorHandler("it happens")
            return nil
        }
    }
}

from dispatchkit.

ElvishJerricco avatar ElvishJerricco commented on June 20, 2024

Alright that makes sense. I'd imagine we'd want the error handler to be a constructor parameter that defaults to the default error handler?

from dispatchkit.

anpol avatar anpol commented on June 20, 2024

No, I expect the global variable errorHandler, or even the static variable within the Dispatch struct.

More important is that I'm not sure we need failable initializers once we have error handler. I suspect it would be better to avoid failable initializers at all and stick to error handler mechanism.

from dispatchkit.

ElvishJerricco avatar ElvishJerricco commented on June 20, 2024

I see a HUGE problem with that approach. If module A depends on B, and both A and B make use of DispatchKit, then only one of them can have an error handler.

Moreover, I'm not sure it makes sense that every usage of these methods should require the use of the same error handler. Shouldn't different scenarios call for different handling?

Also, I'm just not seeing why the error handler is necessary at all. If we want to generate some kind of runtime error, we can throw an ErrorType of some kind. This can be caught, handled case-by-case, and provides any necessary details to the catcher.

Finally, I don't see why any of this is better than just having a failable initializer. It'd be different if we were able to provide detailed error information. But if all we're doing is artificially producing an error and calling a handler or throwing or whatever, how is that different than a failable initializer? If the user wants to use some global handler, they can just surround these methods with their own

guard let x = DispatchType(args...) else {
    errorHandler()
}

Overall, it makes most sense to me to forego error handlers entirely in favor of idiomatic swift, with optionals.

from dispatchkit.

anpol avatar anpol commented on June 20, 2024

OK then, every initializer that wraps GCD API should be defined as init!, what's special about DispatchData initializers?

BTW, what do you think about eliminating duplicate data members like DispatchQueue.queue in favor of DispatchQueue.rawValue?

from dispatchkit.

ElvishJerricco avatar ElvishJerricco commented on June 20, 2024

I just mentioned DispatchData because it has a lot of different initializers and methods which call underlying dispatch methods.

from dispatchkit.

ElvishJerricco avatar ElvishJerricco commented on June 20, 2024

As for eliminating duplicates, I could be wrong, but I'm fairly sure that types that implement a protocol can't change the type of a computed property to a subtype.

Although I supposed it could be genericized.

protocol DispatchObject {
    typealias RawType: dispatch_object_t
    public var rawValue: RawValue

    ...
}

from dispatchkit.

anpol avatar anpol commented on June 20, 2024

It seems promising. Then we are to deprecate init(raw:) too.

The summary of changes proposed so far:

protocol _DispatchObject {
    typealias RawValue : dispatch_object_t
    var rawValue : RawValue { get }
}

struct _DispatchQueue : _DispatchObject {
    @available(*, unavailable, renamed="rawValue")
    var queue: dispatch_queue_t { return rawValue }

    @available(*, unavailable, renamed="_DispatchQueue(rawValue:")
    init!(raw value: dispatch_queue_t) { return nil }

    let rawValue: dispatch_queue_t

    init(rawValue: dispatch_queue_t) {
        self.rawValue = rawValue
    }

    init!() {
        if let queue = dispatch_queue_create(nil, nil) {
            self.rawValue = queue
        } else {
            return nil
        }
    }
}

from dispatchkit.

ElvishJerricco avatar ElvishJerricco commented on June 20, 2024

Looks good to me. And of course introducing the same change to the other Dispatch types.

from dispatchkit.

ElvishJerricco avatar ElvishJerricco commented on June 20, 2024

Do you want me to work on a pull request for this? Or have you already started?

from dispatchkit.

anpol avatar anpol commented on June 20, 2024

Actually, I will not be able to actively maintain this until Dec 22, at least.
I would be happy if you'll get this done.

from dispatchkit.

ElvishJerricco avatar ElvishJerricco commented on June 20, 2024

No problem. I'll get right on it.

from dispatchkit.

Related Issues (5)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.