Hacker News new | ask | show | jobs
by jdonaldson 3061 days ago
I had a big problem with the automatic conversion on return values. This is like saying that Promise<Promise<String>> can't exist, only Promise<String>. This reminds me of when Perl disallowed Array<Array<String>>, insisting that only Array<String> was necessary.

The second drawback to this autoconversion approach is that it enforces a very specific runtime behavior, and requires drawing a line for compliant/non-compliant libraries. I remember reading the github discussion threads marveling at how they were at once dividing the community and crippling such an important feature.

2 comments

You mean this thread? https://github.com/promises-aplus/promises-spec/issues/94

I love reading the for-against monadic promises. It actually is educating just following the discussion.

Yep, that's the one. I think it should be required reading.

Most of the folks in that thread are highly intelligent, and mean well. But to hear them toss out category theory as "impractical" and "not based in reality"?... It's just so cringeworthy. Here's their final spec, which seems absolutely convoluted to me: https://promisesaplus.com/#the-promise-resolution-procedure

Why does any of this matter to non-js devs (like me)? Because some of us want to target javascript with higher level languages, and externing a js promise instance is a necessity. The runtime-driven behavior described here means that the compiler will never really know the type of a given promise resolution. So, the compiler is very limited in what it can handle.

There can be some value in collapsible types, so long as there is a delimiter you can throw in. For instance, you could return a promise in a one-element array.

For Perl (which I don't know) I could imagine the argument went that joining arrays was common enough that having to call an explicit function would get in the way of this common case. Hopefully there was a reasonable way to box up the inner arrays to prevent splicing.

(I've been thinking about this sort of thing recently because I've been looking into J, where an array of arrays in a higher-rank array, which is important because of the way arrays are automatically split up for, say, element-wise operations. Sure enough, J has a delimiter that they call a box, so an array of boxes of arrays is not a rank-2 array.)

Nah, adding allocations isn't a good idea. The goal of a compiler is to do less work and fewer allocations.

The js promise instance is going to be some sort of extern type with special constraints. I imagine most compile-to-js languages roll their own monad-based promise types, and then provide some sort of conversion mechanism in special situations.

Maybe that's the goal of a compiler (though I'm not sure I agree), but that, to me, is somewhat subservient to language design and expressivity.

You can't really dismiss a language feature because an imagined implementation of the compiler would cause lots of small allocations. Just as one concrete example, Python has a special pool of tuples to optimize the case of iterating over key/value pairs in a dictionary (and likely only one tuple is used per for loop). Java does something similar-ish by relying on an Eden space in its generational garbage collector.

In Javascript, if it were the case small delimiter objects were used for promises and they proved to be a performance problem, I can imagine a couple of ways the interpreter could optimize that object out.