Search code examples
lambdaschemelispracketsicp

SICP - Lambda output


I defined the following procedure using Racket and inside the IDE Dr. Racket:

(define (random a b c x)
  (lambda (a b c x)
    (+ (* a (* x x))
       (* b x)
       c)))

As you might see, there is a lambda expression inside it. I tried calling:

(random 4 2 9 3)

And I got as an output:

#<procedure:...ercício-2.4.rkt:16:2>

I thought I would get 51.

Why does this happen? Why does the interpreter return the procedure and not result of the operation?


Solution

  • (define (proc-name args ...) body ...)
    

    Makes a procedure and binds it to variable proc-name. Is an abbrivation for

    (define proc-name 
      (lambda (args ...)
        body ...))
    

    Where in this case define binds a variable to a value and that value happens to be a procedure. If you want to spell out your random it becomes:

    (define random 
      (lambda (a b c x)
        (lambda (a b c x)
          (+ (* a (* x x)) (* b x) c))))
    

    The outer is the procedure that takes arguments a, b, c, and x and the procedure returns another procedure that also takes arguments a, b, c, and x effectively shadowing the original bindings then does some expression on those. An example usage would be

    ((random #f #f #f #f) 4 2 9 3)
    

    Since it's obvious your procedure was not suppose to return a procedure you should either use the short form on top:

    (define (random a b c x)    
      (+ (* a (* x x)) (* b x) c))
    

    Or the equivalent non sugared form:

    (define random 
      (lambda (a b c x)    
        (+ (* a (* x x)) (* b x) c)))
    

    It's common to have procedures return procedures as well as pass procedures as arguments that are used in procedures. Scheme has no idea if a variable binding is a procedure before it is supposed to call it with parentheses such that rookie mistakes like extra parentheses gives the strange error "application: (+ a b) not a procedure" if you try something like ((+ a b) 4)

    An example where return is a procedure can be partial application:

    ; makes a procedure that adds initial
    (define (make-add initial)
      (lambda (v) (+ initial v))
    
    (define add-10 (make-add 10))
    (define add-3 (make-add 3))
    
    (add-3  2) ; ==> 5
    (add-10 2) ; ==> 12