Hey,
I was recently informed about promhx in this list. Now I see the “future” and “signal” feature in tink_core, and I am confused:
Thanks!
Nathan
For one, as far as I understand Justin tried to stick close to the
Promise pseudo-standard
(http://promises-aplus.github.io/promises-spec/) for JavaScript. I was
primarily interested in building something that makes sense from a
Haxe perspective.
Quite frankly I wasn't really aware of promhx when I started out. But
since I had carte blanche, there are quite a few differences.
1. Futures and Signals are readonly. You have to use a SignalTrigger
and a FutureTrigger to be able to write data (i.e. resolve the
promise). This is similar to Scala, where a Future is a readonly
Promise. I considered this important, given that you may not want to
expose write access to client code.
2. In Promhx you cannot unregister handlers. This is in accordance to
the standard. But particularly for signals/streams, this is
impractical.
3. The tink_core library in itself is entirely macro free and declares
primitives and the most common operations on them. Promhx comes with a
number of convenience macros and adapters for JavaScript/jQuery stuff.
I am working to add some of these things in other parts of Tinkerbell,
but to me it was important to keep the core lightweight and small.
4. In tink_core the possibility of errors is expressed through
Outcome. That's because I feel it's important not to blur the line
between systematic failure (e.g. I/O doesn't work because the real
world is a gruesome place) and human failure (e.g. code that causes a
null pointer exception), commonly distinguished as errors and
exceptions. This makes errors visible and first class. So in tink_core
I can distinguish `Future<Result>` and `Future<Outcome<Result,
Error>>` (or `Surprise<Result, Error>` as I like to alias it).
The latter can fail. But if I happen to have an error recovery
function `Error->Result` I can turn the latter to the former and
express that through the type system. As opposed to that, Promhx
treats errors and exceptions the same way and therefore you've got
this separate untyped mechanism for error handling. It also has ways
to recover errors, but they elude the type system.
Any kind of composability can be achieved on the read only versions,
>> Quite frankly I wasn't really aware of promhx when I started out. But
>> since I had carte blanche, there are quite a few differences.
>>
>> 1. Futures and Signals are readonly. You have to use a SignalTrigger
>> and a FutureTrigger to be able to write data (i.e. resolve the
>> promise). This is similar to Scala, where a Future is a readonly
>> Promise. I considered this important, given that you may not want to
>> expose write access to client code.
>
>
> Yes, promhx provides much simpler wrapper in that sense. I suppose that's
> something I could provide read only versions eventually.
so I'm not sure why it is coupled with writability.
To give you my honest opinion: I think this is actually vital. When I
revisited tink_core I considered to build on promhx. The error
handling I could have lived with, but this for me was a no-go.
This is not at all the same. Say a button has a click stream and you
>> 2. In Promhx you cannot unregister handlers. This is in accordance to
>> the standard. But particularly for signals/streams, this is
>> impractical.
>
> That's something I'm working on improving still. However, there's a
> "pause()" method for streams that will momentarily stop the stream, and an
> "end()" method that is permanent.
attach a listener and want to detach it again:
typedef Button = {
var clicked(default, null):Stream<MouseEvent>;
}
You don't want to pause that stream and affect any other listeners
that may be registered (now or in the future).
The approach is ok if you create the click stream on the fly (as with
your jquery thingy), but you can't do the above, which I think is a
pitty, because it makes for a nice type safe interface and it's not
uncommon to do just that with msignal.
I think a separate promhx_jquery and promhx_http would be a better
idea. So that different parts of the library can move at different
speed and so forth. But that's your prerogative ;)
Sure, but going untyped is an unnecessary sacrifice.
> Promhx has special error handling, since I think dealing with errors in
> async code ranges from tedious to unpredictable. You can still treat
> certain errors as first class values (via a wrapped Outcome<T> or similar),
> but promhx provides a totally separate mechanism for handling "everything
> else".
> For instance, "catchError()" will function like a "catch" directive applied
> to the promise chain up until that point. "errorThen" will function like a
> "then", but will map any errors back to useful values, so that the rest of
> the chain can still work from there. It's more of a safety net.
You can look at how the `>>` operator allows to propagate failures
silently but also to deal with them at any point:
https://github.com/haxetink/tink_core#operators
>> Any kind of composability can be achieved on the read only versions,.
>> so I'm not sure why it is coupled with writability.
>>
>> To give you my honest opinion: I think this is actually vital. When I
>> revisited tink_core I considered to build on promhx. The error
>> handling I could have lived with, but this for me was a no-go.
>
> Fair enough. I think it can be added, but will break a lot of code. I'll
> look into it for the next version.
That is the price of progress ... :D