Hacker News new | ask | show | jobs
by shwestrick 539 days ago
Worth mentioning that you can always safely switch between AoS and SoA. Either can represent the other; all you've done is transpose the data. The same is not true of AoE/EoA. The AoE [Spam1, Egg1, Spam2, Spam3, Egg2] has no corresponding EoA that can represent it.

What they're actually doing is an AoE => AoEoA transformation: find batches elements with the same tag and reorder the elements so that redundant tags can be eliminated. Essentially, a kind of run-length encoding. It's a nice idea.

2 comments

Good insight.

Ah... category theory :-)

Array-of-Stuct (AoS) treats order in arrays as meaningful, arrays as lists, so AoS => Struct-of-Array (SoA) doesn't loose information. It is a sound transformation because it is a homomorphism.

Some languages (homoiconic, or with macros or template support) can express this code transformation: e.g. Julia, https://github.com/JuliaArrays/StructArrays.jl, or Rust, https://www.abubalay.com/blog/2019/02/16/struct-of-arrays

In a sense, you can see this transformation through the concept of monads (although Haskell monads or F# computational expressions cannot directly express it, as far as I know). Then the corresponding category diagrams leads to sets or multi-sets (run-length encoding requires or implies some concept of identity, so unordered lists with repetitions = bags and multi-sets are equivalent in this specific context), as the right concept for Enums of Arrays.

Zig can represent AoS to SoA very nicely, it's a favored technique for the Zig compiler itself and well supported by the standard library where it's known as a MultiArrayList.
Another way to represent an EoA that would be homomorphic to AoE would be to use a SoA that as an array of the tags/discremenants, and a separate array containing unions for the values. Although, that would be a little harder to work with.

If the order doesn't matter, you could use a separate field for each variant of the enum.