61 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
			
		
		
	
	
			61 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
;; 2.77
 | 
						|
;; obviously magnitude isn't defined yet on the complex type,
 | 
						|
;; it is only defined in the internal types, i.e. the secondary types.
 | 
						|
;; this means that the first apply-generic will immediately fail.
 | 
						|
;; the reason Alyssa's fix works, is because this makes the
 | 
						|
;; maginute function dispatch to itself when seing the type
 | 
						|
;; '(complex). Then, magnitude will be called with the
 | 
						|
;; internal type - e.g. '(rectangular 3 4), which gives
 | 
						|
;; the correct answer.
 | 
						|
 | 
						|
;; 2.78
 | 
						|
 | 
						|
(defun type-tag (datum)
 | 
						|
  (cond
 | 
						|
    ((consp datum) (car datum))
 | 
						|
    ((numberp datum) 'number)
 | 
						|
    (t (error "unkown type"))))
 | 
						|
 | 
						|
(defun contents (datum)
 | 
						|
  (cond
 | 
						|
    ((consp datum) (cdr datum))
 | 
						|
    ((numberp datum) datum)
 | 
						|
    (t (error "unknown type"))))
 | 
						|
 | 
						|
;; assuming the dispatch function actually calls the function with
 | 
						|
;; the contents of each datum, then you should now be able to just
 | 
						|
;; insert #'+, #'*, #'- and #'/
 | 
						|
 | 
						|
;; 2.79
 | 
						|
 | 
						|
;; 2.81
 | 
						|
;; First, apply-generic is called.
 | 
						|
;; 'exp is not defined on complex numbers. Therefore, the apply-generic
 | 
						|
;; function somewhat mistakenly enters the second branch, and first tries
 | 
						|
;; to find a coercion from the first argument's type to the second argument's
 | 
						|
;; type. It finds this coercion function. But then it calls:
 | 
						|
;; (apply-generic op (t1->t2 a1) a2)
 | 
						|
;; this is a problem, because it now enters an infinite loop. Every time,
 | 
						|
;; apply-generic will try to find the 'exp method, not find it, and try
 | 
						|
;; to coerce the first argument to the second argument's type.
 | 
						|
;; It will succeed, and call itself again.
 | 
						|
;; Since this is a tail call, it will be optimised and this will be reduced
 | 
						|
;; to an infinite loop.
 | 
						|
;;
 | 
						|
;; Something can be done about it. We can simply compare the tags of
 | 
						|
;; the objects before trying to coerce - and we can simply raise an error
 | 
						|
;; if both objects have been coerced to the same type and there is still
 | 
						|
;; no function found. Coincidentally, this would also prevent Louis Reasouner's
 | 
						|
;; previous infinite loop.
 | 
						|
 | 
						|
 | 
						|
 | 
						|
;; In order to be extra spicy, I will be completing the exercises in
 | 
						|
;; the symbolic algebra section through the use of CLOS.
 | 
						|
;; I.e. I will actually build an AST of these objects, and use
 | 
						|
;; methods to parse, interpret and modify them.
 | 
						|
 | 
						|
;; Tomorrow. I will do that tomorrow.
 | 
						|
 | 
						|
 |