Ruby methods are colorless
Ruby’s “colorless” concurrency
- Ruby hides async behavior behind threads and fibers, so most methods look synchronous.
- Fibers plus a scheduler can make many IO operations non-blocking without changing method signatures.
- Some see this as elegant and ergonomic; others warn it hides when code blocks or yields, making reasoning about performance and contention harder.
- Ruby’s GVL limits true parallelism in MRI for CPU-bound code; Ractors or alternative runtimes (JRuby) are suggested for real parallelism.
Async/await and function coloring
- Many comments revisit “function coloring”: async functions returning promises/tasks vs sync ones.
- Critics: coloring forces async all the way up the call stack, leads to duplicated “sync vs async” APIs, complicates refactors, and exposes single-threaded runtimes into user code.
- Supporters: coloring is a feature; it advertises where IO and yields happen, like a lightweight effect system or Rust’s borrow checker for concurrency.
- Several note that upgrading legacy callback-based code to async/await is painful.
Comparisons across languages
- JavaScript: async/await seen as sugar over promises to avoid callback hell, but also as a new “hell” in large codebases.
- Go: goroutines and channels give colorless concurrency, but boilerplate (channels, WaitGroups) and error handling are highlighted; structured concurrency libraries exist.
- C#, Kotlin, Rust, Python: all have colored async; discussion of dual sync/async APIs, cancellation, and structured concurrency.
- Haskell/Scala: cited as examples of “polymorphic over async” via monads; same code can be sync or async depending on the effect type.
- Erlang/Elixir: actor model and preemptive scheduling sidestep much of the coloring debate.
Use cases and performance
- Async/await praised for high-concurrency IO workloads (scrapers, HTTP services, UI latency) and for making potential parallelism visible.
- Others argue threads or actor/message-passing models remain simpler and more robust for many server workloads.
- Game-dev and UI discussions emphasize scheduling, frame deadlines, and that yielding on IO is often unacceptable in real-time loops.
Tooling, API design, and ambiguity
- Several stress IDE support and type annotations as ways to surface async behavior without syntax noise.
- API evolution issues: once a function is async, it tends to stay that way even if internals change.
- No consensus: some prefer explicit async markers; others prefer colorless models with stronger runtimes or richer type systems.