Re: [futures] Persistent/Repeated Future that doesn't resolve

On Thu, Apr 11, 2013 at 6:56 PM, Jake Verbaten <raynos2@gmail.com> wrote:
> Tab Atkins wrote:
>> Hm, Streams *might* work.  However, it looks like they usually still
>> fall prey to the "can only see the *next* update after subscribing"
>> problem.  If we had something that would inform you of the
>> most-recently-published value as well when you subscribed, it would
>> probably work better.  If I'm reading correctly, they also
>> automatically feed you the entire history of the stream, while the
>> use-cases I'm thinking of just need to know the "current" state and
>> future states.
>
> Streams should not feed you the entire history, they should just give you
> new events.

Are you saying that Dart Streams specifically shouldn't, or that
"streams" in general shouldn't?  Because Dart Streams clearly do give
you the whole history, according to the examples on the page Domenic
linked.  You *first* fill a stream with data from an iterable, *then*
listen to the stream, and you get all the data you'd already pushed
in.

> I also feel that progress is out of scope for Future as they represent a
> single value to be known in the future with correct error propagation
> mechanisms.

Once again, this is a narrow view.  "A single value to be known in the
future" can easily and naturally be augmented with progress toward the
completion of that value.  For example, check out the Font#ready()
function I've sketched at
<http://wiki.csswg.org/ideas/font-load-futures>.  Right now it's a
simple Future, which completes/rejects when the font loads/errors.
But font load status is actually tri-state, going from "not loaded" to
"loading" to "loaded", and it's reasonable to augment the Future with
the ability to observe the current state of the Font so that, for
example, a web-based authoring tool could have UI for the current
state of the font.

> As mentioned in another thread (
> http://lists.w3.org/Archives/Public/www-dom/2013AprJun/0022.html ) you
> probably want to look into an FRP style signal (
> http://en.wikipedia.org/wiki/Functional_reactive_programming ) which is a
> representation of a value over time. It's the only async data structure I
> know of that specifically models current state at a moment in time.

Yes, what I'm asking for is more-or-less an FRP signal.

> RXJS ( https://github.com/Reactive-Extensions/RxJS/wiki/Observable ) and
> bacon ( https://github.com/raimohanska/bacon.js#property ) have
> implementations of this idea. Elm (a compile to JavaScript language) also
> has good implementations of this idea (
> http://elm-lang.org/learn/What-is-FRP.elm )

(Btw, the RxJS docs are completely impenetrable.  Most of the
documentation doesn't even exist, and the stuff that does exist is
barely described.  The API has kinda horrible naming in parts, too.)

> It would probably look like
>
> interface Signal {
>   void listen(valueListener);
>   Any value();
> }
>
> Where you can ask it for it's current value synchronously by calling value()
> and you can listen to any future changes by calling listen(function).

This appears to be almost exactly what I proposed, no?  It uses a
value() for the current value, rather than a next() for the next
value, but these can coexist usefully.

> It
> should be noted that the representation of a value over time is not a
> representation for an asynchronous task that may cause an error, that's a
> seperate thing.

Not really.  The progress of an async task is a value over time.  The
two aren't *intrinsically* linked, but neither are they intrinsically
separate.

Further, a value changing over time can still cause an error, and stop
being valid.

> Your font future may have an attribute called "completionStatus" that is a
> signal. It should also be noted that signals require an initial value. In
> the case of the loading status of a font it would default to 0 (assuming
> it's modeled as a number from 0 to 100).

If value() returns a future for the value, rather than returning the
value syncly, then you don't need an initial value either - the
value() future just wouldn't be resolved initially.  (After at least
one value is pushed, the future returned by value() is always already
completed.)

Alternately, the initial value can just be null/undefined.  That works
just fine for most things.

> It should also be noted that streams do not have a notion of "current value"
> for good reasons. The notion of "current value" means that a) you need to
> maintain state on something that could be stateless. b) it needs to have an
> initial state before it has started and c) you need to look at the state of
> a stream in between two events and that state needs to make coherent sense.
> Just saying that the state is the last event is not always a meaningful
> thing.

If the value changes and you dont' push it to your listeners, you're
doing it wrong.  If you're doing it right, the "last value" is always
meaningful, because it's the *current* value.

~TJ

Received on Friday, 12 April 2013 18:06:23 UTC