We could expose rectangular and polar selectors but still use one particular representation under the hood. This is nothing new.
What if we want both representations? Data abstraction allows us to postpone the representation decision, but we don’t want to make a decision at all!
We need a vertical barrier between rectangular and polar forms.
The selectors real-part, imag-part, magnitude, and angle must be generic procedures that work with either representation.
For this to work, we need typed data. We need to tag our data objects with labels telling us the type of their contents.
We can simply cons the symbol 'rectangular or 'polar to the complex number data.
The generic procedures check the type of their argument, strip off the type information, and dispatch the contents to the appropriate specific procedure.
We can also add polynomials to the generic arithmetic system.
Our polynomials will have a variable (symbol) and a term list (list of ordered pairs).
We can add polynomials in the same variable by combining their term lists.
By using the generic add when we add term lists, we can use any kind of number as a coefficient, for free! Including polynomials themselves!
In other words, all because we wrote add instead of +, we have this recursive tower of types: the coefficients can be polynomials all the way down, or as far as we’d like.
If we use the generic arithmetic procedures in the rational number package, we can get rational functions (polynomials over polynomials) for free as well.