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

Now that DOM Futures have moved to accept semantics ("monad
semantics") when a .then() callback returns a Future, there's only one
remaining issue that I want to try and get agreement over.

I am explicitly asking for feedback from Domenic and others who have
experience in the Promises/A+ standardization effort.  More
echo-chamber from us in the "monad camp" won't be particularly
helpful. ^_^

The last issue is automatic assimilation of thenables return by
.then() callbacks.  To be clear, by "thenable" I mean "any object with
a .then() method, which is not a native/branded promise".

I believe that thenables returned by a .then() callback should be
treated as "plain values", and we should add an explicit assimilation
function that does the job of converting a thenable into a native
promise.

My reasoning is that this is necessary for predictability.  "Thenable"
is a structural type - it applies to everything with a .then() method,
regardless of whether it was *intended* to be a promise-like or not.
We already have at least one explicit example of a library returning
objects with a .then() method that aren't promise-like: the Casper.js
library.  I'm sure there are more, and will be more as long as we
don't mess this up.

If we auto-assimilate, it means that anytime we want to return the
value of some function, if we're not sure that the return value is a
primitive or a native promise, we have to use Future.accept() to guard
it against the possibility of accidental and erroneous assimilation.
(Wrapping the value in an accepted promise triggers the monad
semantics, which are safe regardless of what the inner value is.)

So, I propose that we instead expose an explicit assimilation function
that takes a promise-like and returns a native promise.  .then()
callbacks then have a simple two-case semantics, which only check to
see if the return value is a native/branded promise, and otherwise
treat it as a plain value.  This makes promise semantics predictable
and simple, at the minor cost that when crossing library boundaries,
you have to manually assimilate.

(I think this is acceptable, as we already do it in other places.  For
example, jQuery objects are basically DOM Element-likes, but the DOM
methods don't try and use them automatically.  Instead, jQuery lets
you get at the native Element backing them, for when you need to step
back into DOM land.  This would be similar.)

~TJ

Received on Thursday, 2 May 2013 18:36:44 UTC