Hacker News new | ask | show | jobs
by fsantanna 3430 days ago
Thank you, I will improve the page.

In summary:

Reactive: code executes in reactions to events

Synchronous: reactions run to completion, i.e., there's no implicit preemption or real parallelism (this avoids explicit synchronization: locks, queues, etc)

Structured: programs use structured control mechanisms, such as "await" (to suspend a line of execution), and "par" (to combine multiple awaiting lines of execution)

Structured programming avoids deep nesting of callbacks letting you write programs in direct/sequential style. In addition, when a line of execution is aborted, all allocated resources are safely released.

In comparison to FRP/dataflow, it is more imperative supporting sequences/loops/conditionals/parallels. The notion of (multiple) program counter is explicit. Also, everything is lexically scoped, there's no GC involved.

In comparison to promises/futures, it provides lexical parallel constructs, allowing the branches to share local variables and, more importantly, supporting safe abortion of code (with the "par/or").

1 comments

Synchronous: reactions run to completion, i.e., there's no implicit preemption or real parallelism

Does this mean a program will hang if e.g. disk or network access takes too long?

Yes in theory. But in practice the language includes "async" support so you can guard these few operations that may take long. Like in a functional language you assume everything is pure unless marked to have side-effects, here you assume every reaction is instant unless is something that has to be explicitly "awaited" for. It's a pretty clean model.
Another way of thinking about this (also mentioned in the docs somewhere) is that Ceu "pretends" that any reactive code finishes infinitely fast, similar to how garbage collected languages "pretend" that computers have infinite memory.

Neither truly does, of course, but the idea is that for the vast majority of situations where either type of language is used, that's a good enough approximation, letting you vastly simplify the problem that you're solving.

External calls in C require an underscore (e.g., "_printf") to be easily trackable as possibly unsafe.

Also, at some point in the code (e.g., after you include your libraries), one can disable these calls with a directive.

But typically, one will use bindings for asynchronous libraries, such as libuv (https://github.com/fsantanna/ceu-libuv).