Recently when I self-learnt MIT 6.5151 course, I first read CS 61AS Unit 0 as the preparation. Then I have read SICP 1 to 2.1 (with related lecture notes) as ps0 requires (also read 2.2.1 as CS 61A notes requires) and then Software Design for Flexibility (SDF) Prologue, chapter 1 and partly Appendix on Scheme.
I uses MIT-Scheme.
Currently I am reading SDF chapter 2 and doing exercise 2.5 (b).
The following code has weird results throwing errors ";The object square is not applicable." and ";The object (lambda (x) (square x)) is not applicable.". Here func_polynomial_minimal_unit
calculates something like (f(f(g(x)))
when calling (func_polynomial_minimal_unit '((f . 2) (g . 1)))
(define (compose f g)
(define (the-composition . args)
(call-with-values (lambda () (apply g args))
f))
the-composition)
(define (iterate n)
(define (the-iterator f)
(if (= n 0)
identity
(compose f ((iterate (- n 1)) f))))
the-iterator)
(define (identity x) x)
(define (func_polynomial_minimal_unit . func_pow_pair_lst)
(if (null? (car func_pow_pair_lst)) ; contain one null pair
identity
(let ((cur_func_pow (caar func_pow_pair_lst)))
(newline)
(display cur_func_pow)
(compose
((iterate (cdr cur_func_pow)) (car cur_func_pow))
(func_polynomial_minimal_unit (cdr func_pow_pair_lst))))))
;; equivalent lambda for the following `func_polynomial_minimal_unit`.
((lambda (x) (expt (* x 9) (expt 2 3))) 3)
;; these works
((compose ((iterate 3) (lambda (x) (square x))) (lambda (x) (* 3 x))) 3)
((compose ((iterate 3) square) (lambda (x) (* 3 x))) 3)
;; these doesn't work
((func_polynomial_minimal_unit '((square . 3) ((lambda (x) (* 3 x)) . 2))) 3)
((func_polynomial_minimal_unit '(((lambda (x) (square x)) . 3) ((lambda (x) (* 3 x)) . 2))) 3)
But as the above code shows, these procedures can be applicable. So why are these errors thrown?
Symbols and variables are different things. Bare symbols in code are variables (or syntax like let
) and the same symbols in a quoted list are just symbols that has nothing to do with the variable square
or the variable a
When you write code like (square a)
Scheme evaluates the operator, the variable square
. Since it evaluates to a procedure it evaluates the variable a
, then applies the procedure with the evaluated operands.
Now if I were to make a list eg. to-apply
like (define to-apply '(square a)))
and then try to print this (display to-apply)
you'll see the exact same as you wrote because you quoted it. (apply (car to-apply) (cdr to-apply))
will give you the exact same error message as you encountered since the symbol square
is not a procedure.
However if you define it like (define to-apply (list square a)))
and then do (display to-apply)
you'll see something like (#<procedure-suqare> 3)
and (apply (car to-apply) (cdr to-apply))
will give you 9
Instead of list
you can use the quasiquote syntax:
((func_polynomial_minimal_unit `((,square . 3) (,(lambda (x) (* 3 x)) . 2))) 3)
Since numbers are self evaluating you don't need to unquote them, but if you were to use a variable you would need to do it there as well :-)