SICP Exercise 2.77: expected a procedure that can be applied to arguments, given #f
2023-07-13
Categories: Programming
2.5.1 Generic Arithmetic Operations
Louis Reasoner tries to evaluate the expression (magnitude z) where z is the object shown in figure 2.24. To his surprise, instead of the answer 5 he gets an error message from
apply-generic
, saying there is no method for the operationmagnitude
on the types(complex)
.
To simplify the install-complex-package
procedure, I made the following changes:
1(define (install-complex-package) 2 (define (make-from-real-imag x y) 3 ((get 'make-from-real-imag 'rectangular) x y)) 4 (define (tag z) (attach-tag 'complex z)) 5 (put 'make-from-real-imag 'complex 6 (lambda (x y) (tag (make-from-real-imag x y)))) 7 8(install-complex-package) 9 10(trace-define (make-complex-from-real-imag x y) 11 ((get 'make-from-real-imag 'complex) x y)) 12 13(magnitude (make-complex-from-real-imag 3 4))
However, upon running the code, instead of the expected error from apply-generic
, a different error occurred:
1$ racket 2.77-apply-generic-magnitude.rkt 2'done 3>(make-complex-from-real-imag 3 4) 4application: not a procedure; 5 expected a procedure that can be applied to arguments 6 given: #f
I wondered why it returned #f
when 'make-from-real-imag 'complex
had already been put
into the dispatch table:
1$ racket --repl 2Welcome to Racket v8.9 [cs]. 3> (require "2.77-apply-generic-magnitude.rkt") 4> (get 'make-from-real-imag 'complex) 5#<procedure:...neric-magnitude.rkt:75:16>
To debug the issue, I utilized the racket/trace library:
1$ racket --repl 2Welcome to Racket v8.9 [cs]. 3> (require "2.77-apply-generic-magnitude.rkt") 4>(install-complex-package) 5> (put 'make-from-real-imag 'complex #<procedure:...neric-magnitude.rkt:75:16>) 6< #<void> 7<'done 8'done 9> (make-complex-from-real-imag 3 4) 10>(make-complex-from-real-imag 3 4) 11> (get 'make-from-real-imag 'complex) 12< #<procedure:...neric-magnitude.rkt:75:16> 13> (make-from-real-imag 3 4) 14> >(get 'make-from-real-imag 'rectangular) 15< <#f 16application: not a procedure; 17 expected a procedure that can be applied to arguments 18 given: #f 19 [,bt for context]
As a result, it became evident that when we called (make-complex-from-real-imag 3 4)
, it was actually invoking make-from-real-imag 3 4
,
which, in turn, called (get 'make-from-real-imag 'rectangular)
and this returned #f
.
To address this issue, we need to add the install-rectangular-package
procedure mentioned in 2.4.3 Data-Directed Programming and Additivity
to get the expected error:
1>(make-complex-from-real-imag 3 4) 2> (get 'make-from-real-imag 'complex) 3< #<procedure:...neric-magnitude.rkt:75:16> 4> (make-from-real-imag 3 4) 5> >(get 'make-from-real-imag 'rectangular) 6< <#<procedure:...neric-magnitude.rkt:65:16> 7> (attach-tag 'rectangular '(3 . 4)) 8< '(rectangular 3 . 4) 9>(tag '(rectangular 3 . 4)) 10>(attach-tag 'complex '(rectangular 3 . 4)) 11<'(complex rectangular 3 . 4) 12>(get 'magnitude '(complex)) 13<#f 14No method for these types: APPLY-GENERIC '(magnitude (complex))
Related Posts:
- SICP Exercise 2.43: Eight queens: interchange the order of the nested mappings
- SICP Exercise 2.42: Eight queens puzzle
- SICP Exercise 2.41: Triple sum
- SICP Exercise 2.35: Counting leaves of a tree
- SICP Exercise 2.27: Reversing nested lists