W3C home > Mailing lists > Public > public-script-coord@w3.org > April to June 2013

Re: Promises: Auto-assimilating thenables returned by .then() callbacks: yay/nay?

From: Jonas Sicking <jonas@sicking.cc>
Date: Tue, 7 May 2013 23:00:25 -0700
Message-ID: <CA+c2ei-2gD=8wREWMPq7GtHhxy6s-mdna3=PfXo79FTV20iRKg@mail.gmail.com>
To: David Sheets <kosmo.zb@gmail.com>
Cc: Sam Tobin-Hochstadt <samth@ccs.neu.edu>, "Tab Atkins, Jr." <jackalmage@gmail.com>, Domenic Denicola <domenic@domenicdenicola.com>, "public-script-coord@w3.org" <public-script-coord@w3.org>, "Mark S. Miller" <erights@google.com>
On Tue, May 7, 2013 at 6:05 PM, David Sheets <kosmo.zb@gmail.com> wrote:
> On Wed, May 8, 2013 at 12:38 AM, Jonas Sicking <jonas@sicking.cc> wrote:
>> On Tue, May 7, 2013 at 3:16 PM, David Sheets <kosmo.zb@gmail.com> wrote:
>>> On Tue, May 7, 2013 at 11:03 PM, Jonas Sicking <jonas@sicking.cc> wrote:
>>>> On Mon, May 6, 2013 at 10:40 AM, Sam Tobin-Hochstadt <samth@ccs.neu.edu> wrote:
>>>>> On Mon, May 6, 2013 at 1:25 PM, Jonas Sicking <jonas@sicking.cc> wrote:
>>>>>> On Fri, May 3, 2013 at 7:10 PM, Sam Tobin-Hochstadt <samth@ccs.neu.edu> wrote:
>>>>>>> On Fri, May 3, 2013 at 7:17 PM, Jonas Sicking <jonas@sicking.cc> wrote:
>>>>>>>>
>>>>>>>> Third, there's the question of what a nested promise actually means.
>>>>>>>> Normally a promise represents "a value after some time". But what does
>>>>>>>> a nested promise mean? "A value after a longer time" obviously isn't
>>>>>>>> correct since there are no time constraints associated with a promise.
>>>>>>>> "A promise after some time" also isn't really meaningful given that
>>>>>>>> that simply means "A value after some time after some time".
>>>>>>>
>>>>>>> I've been staying out of all of the promises discussions, but this
>>>>>>> just doesn't make any sense at all.  A function of no arguments is a
>>>>>>> "computation that produces a value".  By a similar argument to yours,
>>>>>>> functions of no arguments that produce the same aren't meaningful,
>>>>>>> because it's a "computation that produces a computation that produces
>>>>>>> a value".  I hope we can all see that this in fact makes perfect
>>>>>>> sense.
>>>>>>
>>>>>> The difference is that it's meaningful for a function that takes no
>>>>>> argument to return a function that takes no argument. That provides
>>>>>> the capability for the caller of the initial function to determine
>>>>>> when the returned function should be called. Thus it lets the caller
>>>>>> postpone the CPU cycles spent by the returned function until the
>>>>>> result is actually needed.
>>>>>>
>>>>>> To put it another way a "computation that produces a computation that
>>>>>> produces a value" is meaningful since you can choose to not perform
>>>>>> the second computation if it turns out that you don't need it.
>>>>>
>>>>> This is silly in just the same way.  Given a promise, we can choose to
>>>>> wait for its result, or not, just as with a function, we can run it or
>>>>> not.
>>>>
>>>> No. Existing promise libraries are built around the idea that the
>>>> calculation to create the value always happens, no matter if someone
>>>> has said they are listening to the promise or not.
>>>
>>> Could you please explain which part of the promise concept makes this
>>> eager evaluation necessary?
>>
>> The promise concept doesn't. But I've not seen any libraries that
>> permit it. I.e. I haven't seen any libraries that allow the creator of
>> the promise to be notified when someone registers to be notified about
>> the value.
>
> The promise can side-effect and that is how an observer will be notified.
> No additional API is required -- merely a different type of promise
> that obeys the same contract.
>
>>>> So they do not provide the ability to postpone a calculation until
>>>> someone that has access to the promise requests the calculation to be
>>>> performed.
>>>
>>> I have a promise library on my disk that does provide this ability. It
>>> is a trivial extension.
>>
>> The question isn't what can be implemented. The question is what
>> existing libraries and code does as that is an indication of what
>> people have requested.
>
> Not many people thunk
> <http://en.wikipedia.org/wiki/Thunk_%28functional_programming%29>.
>
> Erm, I guess except people who coded in Algol 60 and pretty much any
> language since with first-class functions...
>
>>>>>> Nor have anyone brought forward any use cases.
>>>>>
>>>>> Consider a hash table that keeps some state remotely. Then a promise
>>>>> is useful for the results.  If promises for promises are impossible,
>>>>> can you store promises in the table?
>>>>
>>>> This is similar to the example I brought up, except that you store the
>>>> values in a hash table rather than storing them in a database.
>>>>
>>>> This is indeed an interesting use case. One relevant question is: What
>>>> is the use case for getting the promise stored in the hash/database,
>>>> rather than getting the value that the promise represents?
>>>>
>>>> In your hash table example as a consumer I would think it's great if
>>>> what I get out of the API is values rather than promises so that I
>>>> don't have to bother with additional (recursive?) calls of .then().
>>>>
>>>> One reason that was brought up was that if getting the promise from
>>>> the hash is fast, but getting the value from the promise is slow, then
>>>> the caller might want to know about the intermediate step of having
>>>> the promise from the hash.
>>>>
>>>> So essentially this is a way of modelling progress by having several
>>>> nested promises. Each unwrapping callback represents an indication of
>>>> progress.
>>>>
>>>> I'm not sure if this is a great way of modelling progress though. The
>>>> ProgressFuture that has been proposed seems like a more robust
>>>> solution to me.
>>>
>>> If you're happy with ProgressFuture, that's great. If someone else
>>> wants to use nested promises to achieve this, will you tell them "you
>>> can't, that's not 'robust'"?
>>
>> If we're creating a standardized API, we have to create a limited
>> feature set.
>
> Great! Limit your features to the minimal necessary including not
> disallowing compatible promises, not overspecifying evaluation order
> and not breaking encapsulation through forced calculation of a
> promise's fixpoint.
>
>> We can't support everyone's use cases and everyone's
>> requirements. Those are the breaks.
>
> Supporting everyone's desires /ever/ is clearly unachievable in the
> general case. Luckily, our problem is much simpler than the general
> case.
>
> The present concern regards the tension between:
>
> 1. Precisely who gets to build compatible promises
> 2. How much of their behavior is mandated
> 3. How general-purpose they are
>
> If I understand correctly, you advocate decreeing at least: (2)
> specific unnecessary details of evaluation and (3) limitations on
> their general-purpose usage. To enforce these decrees, you will
> consequently need to (1) limit who gets to write compatible promise
> implementations. Your approach prohibits some use cases for, from what
> I can tell, 2 primary reasons: 1. if you intentionally use them and
> don't know what you're doing, they can be confusing and 2. you haven't
> seen JavaScript promise library users using them. Is this correct?
> Have I misrepresented your argument?

I confess that I don't follow what you are saying above at all.

What I'm trying to do is to define a API exposed to javascript code
running in the web platform. I do not intend to define what every
promise library must do. Anyone writing a library is free to do
whatever they want to do.

But yes, I definitely think we should precisely define how that API
behaves, which by extension defines how you must write code to be
compatible with that API. Generally in order to make things
interoperable between implementations that means that we much very
tightly mandate a particular behavior.

/ Jonas
Received on Wednesday, 8 May 2013 06:01:29 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:37:49 UTC