Function Colors Represent Different Execution Contexts "function colors" represent genuine differences in execution contexts (e.g., async vs. sync, CPU vs. GPU) that cannot be eliminated through type systems or syntactic workarounds. It criticizes efforts toward "colorblind programming" as fundamentally misguided, advocating instead for embracing these boundaries and developing first-class, composable execution bridges to manage context transitions explicitly. The core insight is that the problem lies not in the colors themselves, but in the lack of robust, composable tools for crossing execution context boundaries. Function colors represent different runtime machinery required to execute blocks of code. The common framing of colors as side effects that "contaminate" code is fundamentally misleading. This mental model leads developers down unproductive paths, chasing effect systems to track and compose side effects, or other solutions that address symptoms rather than the underlying reality. A prevalent misconception treats function colors as merely a type system problem. For example, Yoshua Wuyts' post on extending Rust's effect system exemplifies this approach, attempting to manage and compose effects through increasingly sophisticated type machinery. Similarly, efforts toward "colorblind programming" typically follow several unsuccessful strategies: These approaches treat the problem as purely syntactic, "just apply threads/green threads/effect systems and the colors disappear." But attempts along these lines haven't eliminated function colors in practice, because they fundamentally misunderstand what colors represent. Function coloring extends far beyond the typical async vs sync dichotomy. Consider these execution context boundaries: These aren't arbitrary type annotations, they represent genuine differences in how code must be executed. The colors serve as essential signals to both programmers and compilers about execution requirements and the need for "execution bridges" when crossing context boundaries. Instead of trying to eliminate these fundamental boundaries, we should focus on making context transitions explicit and composable. The constraint isn't on the output side "async functions return Promises" , but on the input side "async functions need state machine runtime to execute" . This is analogous to calling GPU code from CPU code - these represent fundamentally different execution environments that require explicit bridging mechanisms. The problem isn't that they're different, it's that most languages provide only ad-hoc, non-composable solutions like await and spawn . Current execution bridges are typically: What we need are first-class execution bridges that: Clojure's approach with macros and atoms provides a glimpse of this - its macro system enables flexible context management, while atoms handle shared state across execution boundaries. However, this pattern doesn't translate well to languages without powerful macro systems. The solution isn't to eliminate function colors, but to embrace them as useful abstractions while building better tools for managing the transitions between execution contexts. Function colors reflect genuine execution context differences that can't be abstracted away without cost. Rather than pursuing the impossible goal of colorblind programming, we should focus on developing composable, first-class execution bridges that make context transitions both explicit and manageable. The time spent trying to eliminate function colors would be better invested in understanding and tooling around the execution context boundaries they represent.