functionargumentsschemeparameter-passingmit-scheme

"The object square is not applicable" but `square` is one internal procedure in MIT-Scheme


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?


Solution

  • 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 :-)