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

Re: A Challenge Problem for Promise Designers

From: David Sheets <kosmo.zb@gmail.com>
Date: Sat, 27 Apr 2013 17:55:33 +0100
Message-ID: <CAAWM5TyWw1J1AwogDFbnT_T7Q5dAts00xuUK+QNx9prANMpznQ@mail.gmail.com>
To: Ron Buckton <rbuckton@chronicles.org>
Cc: David Bruant <bruant.d@gmail.com>, "Tab Atkins Jr." <jackalmage@gmail.com>, es-discuss <es-discuss@mozilla.org>, "Mark S. Miller" <erights@google.com>, "public-script-coord@w3.org" <public-script-coord@w3.org>, Mark Miller <erights@gmail.com>, Dean Tribble <tribble@e-dean.com>
On Sat, Apr 27, 2013 at 5:21 PM, Ron Buckton <rbuckton@chronicles.org> wrote:
> Here is a case where flattening helps:
>
> function executeAndWaitForComplete(command) {
>   return getJSON(commandUrl + command)
>     .then(function (commandResult) {
>       if (commandResult.complete) {
>         return commandResult.model;

This gets automatically lifted into Future, resulting in Future<typeof
commandResult.model>.

>       }
>       var statusUrl = commmandResult.statusUrl;
>       return pollForCommandComplete(statusUrl);

This is always a Future and becomes the result of
executeAndWaitForComplete with type Future<typeof
commandResult.model>.

>     })
> }
>
> function pollForCommandComplete(statusUrl) {
>   return new Future(function(resolver) {
>     var poll = function (pollResult) {
>       if (pollResult.done) {
>         resolve.resolve(pollResult.model);
>       }
>       else {
>         setTimeout(function() {
>           getJSON(statusUrl).done(poll, resolver.reject);
>         }, 500);
>       }
>     }
>     getJSON(statusUrl).done(poll, resolver.reject);
>   });
> }
>
> In this example, the server will receive a command from the client and will
> process it asynchronously. The client then needs to poll an endpoint to
> check for completion of the command. Just using Futures, flattening is
> helpful here. Without flattening, executeAndWaitForComplete would could
> return either a Future<object> OR return a Future<Future<object>>.

I think the major point of confusion in these discussions is the
result of the framing of the discussion in terms of "flattening". I
believe most beneficial viewpoint is that of "autolifting".

That is, the exceptional case is not when the function argument of
"then" returns a Future+ that gets "flattened" but rather when the
function argument of "then" returns a non-Future that gets
automatically lifted into a Future.

This change in perspective is non-obvious because in many of these
APIs there is no succinct lifting operation to make a Future from
another value. This is a major reason why something like Future.of
(Future.accept) is important.

> In a non
> flattening world, the developer would have to change the function to:
>
> function executeAndWaitForComplete(command) {
>   return new Future(function(resolver) {
>     getJSON(commandUrl + command)
>       .done(function (commandResult) {
>         if (commandResult.complete) {
>           resolver.resolve(commandResult.model);
>         }
>         var statusUrl = commmandResult.statusUrl;
>         pollForCommandComplete(statusUrl).done(resolver.resolve,
> resolver.reject);
>       }, resolver.reject)
>     });
> }

In a non-flattening (and non-autolifting) world, this would be the code:

function executeAndWaitForComplete(command) {
  return getJSON(commandUrl + command)
    .then(function (commandResult) {
      if (commandResult.complete) {
        return Future.accept(commandResult.model);
      }
      var statusUrl = commmandResult.statusUrl;
      return pollForCommandComplete(statusUrl);
    })
}

The only difference here is that commandResult.model is explicitly
wrapped. This is because the signature of then is actually Future<a>
-> (a -> Future<b>) -> Future<b>.

David
Received on Saturday, 27 April 2013 16:57:28 UTC

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