Summary
From this exercise, I would draw the following principles:
- If you have an actual, factual performance concern, then avoid multimethods in favor of a plain function or protocol functions.
- You should never extend a multimethod or protocol that you do not own to a type that you do not own.
- If you are designing a library that requires some abstraction, you do not want to define a multimethod or protocol; you want to allow a user to pass in a function.
- If you are extending an abstraction to types or something that can reasonably be modeled as types, then protocol functions will provide the best balance between flexibility and performance.
- If you are more concerned about writing cross-platform code and less about flexibility or performance, then using a plain function with a cond and cross-platform predicates for dispatch would be best.
- If you need very general dispatch and are fine with the performance penalty, then use multimethods.