GithubHelp home page GithubHelp logo

Comments (13)

khanlou avatar khanlou commented on August 22, 2024 2

In the example, the issue is that your block is longer than one line, so its type is not inferred. Via the readme:

As long as the block you pass to then is one line long, its type signature will be inferred, which will make Promises much easier to read and work with.

from promise.

khanlou avatar khanlou commented on August 22, 2024

I wonder if this is because of the type inference on the value 3. It doesn't know if it's an Int, UInt, CGfloat, Int8, etc. Can you try it with an empty struct like struct MyStruct { }?

from promise.

isaac-weisberg avatar isaac-weisberg commented on August 22, 2024

@khanlou oh no no, Int and 3 are just for reference
Here's a snippet from an actual project

var giftController: Promise<GiftIntroductionController> {
    imagePromise.then { userImage in
        return GiftIntroductionControllerBackend.make(for: gift, image: userImage)
    }.then { backend -> GiftIntroductionController in // Here, type will not be inferred if not specified explicitly
        let controller = UIStoryboard.main.instantiate(GiftIntroductionController.self)
        controller.prepare(for: backend)
        return controller
    }
}

N.B.: the return type of closure in then is not necessarily the same as the one and only parameter type, it just happened to be so in the snippet.

from promise.

khanlou avatar khanlou commented on August 22, 2024

@isaac-weisberg is this good to close now or is there still an issue?

from promise.

isaac-weisberg avatar isaac-weisberg commented on August 22, 2024

Still an issue, planned to try to dig more this weekend, if you don't mind :)

from promise.

isaac-weisberg avatar isaac-weisberg commented on August 22, 2024

🤔🤔🤔 I am struggling trying to replicate this behavior with Swift 4.1 on Linux

from promise.

isaac-weisberg avatar isaac-weisberg commented on August 22, 2024

Alright, evidently, the issue is not with version of Swift, I have tuned test up a bit and it started to appear

from promise.

isaac-weisberg avatar isaac-weisberg commented on August 22, 2024

Alright, so first wave of experiments is to be referred to as "done".

The compiler was ultimately confused by the following construct.

        let promise = Promise { fulfill, reject in
            fulfill(SomeStuff())
        }.then { value in
            return Promise { fulfill, reject in
                fulfill(Apple(str: "Heoooo"))
            }
        }.then { apple in
            return Bapple.make()
        }.then { bapple in
            print("Bapple is \(bapple)")
            return bapple
        }

About the last then closure, the output is.

PromiseTypeInferringTests.swift:49:20: error: unexpected non-void return value in void function
            return bapple

Observation 1: so we've got 3 then methods. One of them is generic with closure returning a Promise, another - generic with closure returning a value, creating a Promise itself, and third one - non-generic with closure returning Void. Since Void is a first-class type in Swift, just like functions, a set containing Void type is a strict subset of a set containing all possible types satisfying unconstrained generic type specifier.

Observation 2: third then method features an optional onRejected parameter (that has a default value), while the rest of the then methods don't feature such capabilities. From a logical standpoint, as well as the majority of use cases, a then method with onRejected handler is a done method. With the background of previous observation, this may or may not play some role in compiler's decisions, and if so, the implementations must especially be available both ways.

from promise.

isaac-weisberg avatar isaac-weisberg commented on August 22, 2024

So, possible solution:

  1. Start treating Void as NewValue
  2. Remove then with callback that returns Void
  3. Make the old then with two callbacks the new done, optionally, for internal usage only.

from promise.

isaac-weisberg avatar isaac-weisberg commented on August 22, 2024

Lol so I tried it

Good thing:

  1. it compiles.

Bad thing:

  1. If you had a Promise<Int> and then applied a then handler that returned Void, the type of returned promise is transformed to Promise<Void>

Extract from PromiseTests.swift

        let promise = Promise(value: "someString").then({ string in
            return string.count
        }).then({ count in
            return count*2
        }).then({ doubled in
            XCTAssertEqual(doubled, 20)
            expectation?.fulfill()
        })

Before the changes, type of promise is Promise<Int>, after - Promise<Void>, cause it chains.
@khanlou, I imagine, this is not the desired behavior but wait, it is in fact the desired behavior, obviously, because what we are actually doing is applying not a then handler, but the done handler; in other words, we explicitly specify that we are not chaining another action.

P.S.: one might be wondering "Hey, Isaac, but did this resolve your issue that you had with type inferring?". Answer is no 😂

from promise.

isaac-weisberg avatar isaac-weisberg commented on August 22, 2024

So obviously, with this change to API, all usages of not-chaining then must be changed to done.
And, naturally, done must be public.

from promise.

isaac-weisberg avatar isaac-weisberg commented on August 22, 2024

I have done this and it looks concise and beautiful but this did not resolve the issue. I will fiddle with is just a bit more, maybe it will work, but there is no reason to presume something is going to get fixed eventually in that regard.

from promise.

isaac-weisberg avatar isaac-weisberg commented on August 22, 2024
        let promise = Promise { fulfill, reject in
            fulfill(SomeStuff())
        }.then { value in
            return Promise { fulfill, reject in
                fulfill(Apple(str: "Heoooo"))
            }
        }.then { apple in
            return Bapple.make()
        }.then { bapple in
            print("Bapple is \(bapple)")
            return bapple
        }

produces

PromiseTypeInferringTests.swift:47:16: error: unable to infer complex closure return type; add explicit type to disambiguate
        }.then { bapple in
               ^
                        -> (PromiseTypeInferringTests.Bapple)

Well, that was fun while it lasted :)

P.S.: Just in case, @khanlou, I understand the dramatic nature of changes that I used to propose and I have no hard feelings about the idea of having my PR rejected :) I can guess, the project wouldn't like to have such a drastic change to the API :)

from promise.

Related Issues (20)

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.