Com S 342 meeting -*- Outline -*- * combining data of different types (2.5.2) Q: how can we work with numbers of different types? Crossing type boundaries, e.g., adding an integer and a complex number. Goals: introduce cross-type operations, data abstraction boundaries and additivity ** cross-type operations *** write a different procedure for each combination -- multimethods ;; to be included in the complex package (define (add-complex-to-schemenum z x) (make-from-real-imag (+ (real-part z) x) (imag-part z))) (put 'add '(complex scheme-number) (lambda (z x) (tag (add-complex-to-schemenum z x)))) Q: what other methods would be needed? Q: if we do this, how many operations are needed when we added new types a system with n types and k binary operations? 2*n*k There is also a software engineering issue: Q: who takes care of the maintenance of these cross-type operations? There is no natural package that is responsible for them Language support can help, however, imagine that we can just write: (define (+ z@complex x@number) (make-from-real-imag (+ (real-part z) x) (imag-part z))) to get the same effect. Also, we can avoid writing so many methods if we can use subtyping... ** coercions (p. 195) "In the general situation of completely unrelated operations, acting on completely unrelated types, implementing explicit cross-type operations... is the best that one can hope for" However, when types are related, one way to do better used to treat objects of one type as if they were objects of another type. Coercions: procedural manifestations of this idea don't think of them as necessarily producing a new object. example: (define (scheme-number->complex n) (make-complex-from-real-imag (contents n) 0)) use a "coercion table" indexed by the names of the types (put-coercion 'scheme-number 'complex scheme-number->complex) *** using coercions Q: how could we use the coercions in apply-generic? the book tries to coerce calls to two argument procedures by first coercing the first argument's type to the second's, and then vice versa coercing the second argument's type to the first Q: how many procedures do we have to write compared to previously? n square procedures for n different types *** hierarchies of types (p. 197) relations between types that may be domain-specific can help avoid the need for writing so many coercions For example, the integers as a subtype of the rationals complex supertypes ^ | real ^ | rational ^ | integer subtypes having types in a total order like this allows one to compose coercions easily, and avoids having to write some may coercions for example, one can write a "raise" procedure, to move both operands up to the same level in the tower Q: does this allow for inheritance of operations? Yes, one can use a coercion to apply an operation to a subtype. *** inadequacies of hierarchies in general, one does not get a tower of types, example: geometric figures (figure 2.26) this makes for difficult problems in coercion, because there's no unique supertype that is best ** subtyping by protocol, without coercion ideally, we would like coercions to be automatic When dealing with mutable objects, the coercion cannot produce a new object because the object identity matters some make sure that each object of a subtype *is* an object of each of its supertypes Q: this happens in Java, how? Q: what are subtypes in Java? Q: how are operations generic in Java? Q: does this work in any system with a message passing?