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?
(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