Skip to content

Instantly share code, notes, and snippets.

Understanding Comparative Benchmarks

I'm going to do something that I don't normally do, which is to say I'm going to talk about comparative benchmarks. In general, I try to confine performance discussion to absolute metrics as much as possible, or comparisons to other well-defined neutral reference points. This is precisely why Cats Effect's readme mentions a comparison to a fixed thread pool, rather doing comparisons with other asynchronous runtimes like Akka or ZIO. Comparisons in general devolve very quickly into emotional marketing.

But, just once, today we're going to talk about the emotional marketing. In particular, we're going to look at Cats Effect 3 and ZIO 2. Now, for context, as of this writing ZIO 2 has released their first milestone; they have not released a final 2.0 version. This implies straight off the bat that we're comparing apples to oranges a bit, since Cats Effect 3 has been out and in production for months. However, there has been a post going around which cites various compar

import options
import typetraits
template hasValue[T](o: Option[T]): bool =
proc default(): T = discard
let isSome = o.isSome()
(let `o` {.inject.} = (if isSome: o.get() else: default()); isSome)
let x = some(123)
@andymatuschak
andymatuschak / States-v3.md
Last active June 12, 2024 04:17
A composable pattern for pure state machines with effects (draft v3)

A composable pattern for pure state machines with effects

State machines are everywhere in interactive systems, but they're rarely defined clearly and explicitly. Given some big blob of code including implicit state machines, which transitions are possible and under what conditions? What effects take place on what transitions?

There are existing design patterns for state machines, but all the patterns I've seen complect side effects with the structure of the state machine itself. Instances of these patterns are difficult to test without mocking, and they end up with more dependencies. Worse, the classic patterns compose poorly: hierarchical state machines are typically not straightforward extensions. The functional programming world has solutions, but they don't transpose neatly enough to be broadly usable in mainstream languages.

Here I present a composable pattern for pure state machiness with effects,

@Araq
Araq / LL.rst
Last active May 30, 2024 13:00

This document describes how Lambda Lifting (LL) works. LL is responsible for transforming 'closures' into (environment, function) pairs.

The basic approach is that captured vars need to be put on the heap and that the calling chain needs to be explicitly modelled. Things to consider:

proc a =
  var v = 0
/** Fixed point combinator: The essence of recursion */
def fix[T, R](f: (T => R) => (T => R)): (T => R) = new Function1[T, R] {
def apply(t: T): R = f(this)(t)
}
/** Factorial definition with fixed point */
def factorial(recursive: Long => Long) = (x: Long) => x match {
case 1 => 1
case x => x * recursive(x-1)
}