You haven't written vtables by hand here. Furthermore there's no need for protocols or macros here. You've basically accomplished what's stated. Showing encapsulation (assuming you put this all in a module) of data and behavior without OOP. This is pretty much the same amount of code it would take to write this in a OOP style as well.
Unless you're subtyping, which is where vtables become required, classes vs structures and modules are more or less identical. Unless of course you're trying to encapsulate more than one data type together with a set of behavior, in which case most class systems are incapable whereas with modules it's trivial.
You're right; I forgot to account for subclassing.
If I switched off of pattern matching to pull out the closures and instead used Kernel.elem, it would work with tuples of varying length. Then you'd be able to write subclasses by replacing the closures with your own, and add additional items to the end to add more methods.
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.