Too often, I see arguments of the general form: “I can transform feature X into Y, and the reverse, while maintaining relevant properties. I have an isomorphism. Therefore, I don’t see the difference between X and Y.” For the arguments I’m likely to participate in, X and Y tend to be languages, features, abstractions, protocols, frameworks, or design patterns.
The problem with this line of argument: it assumes transformation is trivial in context, i.e. from the perspective of a language’s user.
For expressive equivalence, we need continuity and locality in addition to isomorphism. Assuming Px is a program from language X, and Py is a program from Y resulting from the translating Px:
- continuity: every small change in a Px results in a small change in Py. Continuity can be expressed in terms of an asymptotic epsilon bound (as the change in Px approaches zero size, the change in Py also approaches zero).
- locality: a bounded change in Px results in a change with a corresponding boundary in Py. Essentially, the transform respects modularity and encapsulation.
Isomorphism is not enough. But it is a good place to start.