Search code examples
schemesicp

Unclear how the get procedure works inside apply-generic (SICP)


In the book The Structure and Interpretation of Computer Programs, Section 2.4.3, it says that:

(get <op> <type>) looks up <op>,<type> entry in the table and returns the item found there.

and apply-generic is defined as

(define (apply-generic op . args)
  (let ((type-tags (map type-tag args)))
    (let ((proc (get op type-tags)))
      (if proc
          (apply proc (map contents args))
          (error "No method for these types: APPLY-GENERIC"
                 (list op type-tags))))))

(map type-tag args) returns a list but shouldn't get expect a single symbol as its second argument in (get op type-tags)?


Solution

  • In the preceding defintion of install-polar-package you'll see the 'signature' of each these procedures is a list:

      ...
      (put 'real-part '(polar) real-part)
      (put 'imag-part '(polar) imag-part)
      (put 'magnitude '(polar) magnitude)
      ...
    

    I.e., in each case '(polar), not 'polar, is put in the table, so to match this we need to pass '(polar) to get.

    The procedures we are applying at the moment are all unary. real-part, imag-part and magnitude only take one argument. In the next next section, 2.5.1, we insltall procedures that take two arguments and therefore we need to match on two types, e.g, the basic arithmetic operators add, sub, mul and div:

      (put 'add '(scheme-number scheme-number)
           (lambda (x y) (tag (+ x y))))
      (put 'sub '(scheme-number scheme-number)
           (lambda (x y) (tag (- x y))))
      (put 'mul '(scheme-number scheme-number)
           (lambda (x y) (tag (* x y))))
      (put 'div '(scheme-number scheme-number)
           (lambda (x y) (tag (/ x y))))
    

    In these cases both the arguments happen to be the same type, but this approach supports procedures with an arbitrary number of arguments of different types.

    Comparision of type-tags to the signature in the table could done with a procedure like equals?, introduced int Ex 2.54, which tests for structural equality. I.e. that the contents of the two lists are the equivalent.