Mitranim

Joined 12 years ago

Karma
72
Submissions
42
Member since
May 9
Autodidact. Software developer. Open source enthusiast.

Chat me up on Skype: mitranim.web

http://mitranim.com

View on Hacker News

Recent submissions

Comment · 9 years ago
Comment · 9 years ago
Comment · 9 years ago
It sounds like you're saying "explicit FSMs are strictly more powerful than promises/coroutines". Which is true. However, they're inherently difficult to program. In my view, the key to simplicity and correctness of programs is reducing the amount of states the program can possibly have. Isolating a piece of code into a blocking sequence seems like a fairly good way of doing it.

Not sure what you mean by "simple examples without error handling". Just like normal synchronous code, promises and coroutines use exceptions, which have the nice property of composability: one catch for several statements/promises. So error handling is the same as in synchronous code.

Now granted, there's a LOT of async/reactive problems where sequential abstractions like promises are irrelevant. GUI programming comes to mind, where you want the view to reflect some reactive state that changes in arbitrary order.

Comment · 9 years ago
That's what the mapping operators are for: `.mapResult` (same as `promise.then`), `.mapError` (same as `promise.catch`), or `.map`. The latter has an errback signature, like Node.js callbacks. They can also return new futures, transforming the result asynchronously. On top of that, error handling in promises/futures is much easier than in callbacks, as you can use one error handler for a chain of operations. Kinda like exceptions in synchronous code.
Comment · 9 years ago
Comment · 9 years ago
Interesting! Nice that the approach is known, and others are being discussed. I should check GTOR again.

Multicast cancelation based on refcounting doesn't look right to me. I explicitly avoided this in Posterus, sticking with exclusive ownership, what GTOR calls unicast (thanks for linking). The reason is that subscribers may come and go over time. I've seen, and written, code that caches a promise and reuses it many times. It may start with one consumer, lose it, be canceled, then another consumer comes and gets rejected. This just feels like a big footgun. In Posterus, multicast is explicit and opt-in (`.weak()` futures).

If we eventually standardise a solution, I'd like something with as few interfaces as possible. In a dynamic language, you don't have the luxury of creating a future that initialises into a task, returning a cancelation token. Too many types without static checking is just a footgun. This is part of why Posterus only has futures, why cancelation is provided in the future constructor and tied to the future itself, and why they're eager rather than lazy. Deviating from these constraints would introduce new types, increasing the footgun potential.

Comment · 9 years ago
This is news to me. Last time I tried RxJS, was unable to get a usable core less than 100 KB minified (I don't use gzip as a metric). Would consider 20-30 KB. Might want to look again.

Bundle size: a typical SPA imports multiple libraries, they import more libraries, and so on. It's not just Rx. I shouldn't have to explain how small things add up. Not caring about size is how it balloons up. We have to care about it in every library.

Comment · 9 years ago
For one operation, sure. It doesn't work when you want to compose multiple async operations, wait until all are finished, or race several of them to completion (e.g. useful operation competing against timeout). The purpose of promises/futures is this composability that allows you to get the order and timing of operations right.
Comment · 9 years ago
No disagreement here. Rx observables are strictly more powerful than promises/futures/streams.

But why start with the superset? I don't think it's good design. Consider the perspective of a language designer. You want to start with primitives that are as simple as possible while satisfying a vast number of real use cases. One-short async primitives are an important intermediary step towards observables, it shouldn't be skipped. Observables should be implemented in terms of these.

This layered design gets you a smaller cognitive cost of entry (promises are hard enough as it is!) and higher efficiency for the vast number of cases that don't need stream-like functionality.

On top of that, one-shot primitives are conceptually compatible with blocking expressions in coroutines such as async/await, whereas streams are not.

I don't get it when people shoot for fat primitives that do it all.

Comment · 9 years ago
This is news to me. Last time I looked into RxJS, I was unable to get a minimum useful core of less than 100 KB minified. Might want to look again, thanks!
Comment · 9 years ago
Correct. Most websites are better off with static HTML or server-side rendering and the least possible amount of JS. However some apps DO have to be fat. And don't forget about Node.js.
Comment · 9 years ago
Doesn't sound as ergonomic as just returning a cancelation function in a future initialiser. Not seeing any other advantages, either. Am I missing some?
Comment · 9 years ago
Agreed, often it doesn't matter. Sometimes it DOES matter (high latency / low bandwidth / weak device), and then your program is slower than it could be. Why not pursue async primitives that let you manage resources properly at no downside?
Comment · 9 years ago
Comment · 9 years ago

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton