Currently working through the Racket Guide at https://docs.racket-lang.org and reading up on lambda functions. The explanation of their usefulness is lucid, but I am not sure I quite grasp the order in which such functions are evaluated. Consider the following example from the Guide:
(define (twice f v)
(f (f v)))
(define (make-add-suffix s2)
(lambda (s) (string-append s s2)))
(twice (make-add-suffix "!") "hello")
The function call to twice
here is said to evaluate to "hello!!"
. Here is my guess at what the evaluation process looks like:
(twice (make-add-suffix "!") "hello")
((make-add-suffix "!") ((make-add-suffix "!") "hello")
((make-add-suffix "!") (string-append "hello" "!"))
(string-append (string-append "hello" "!") "!")
(string-append "hello!" "!")
"hello!!"
Is this an accurate assessment, or have I missed something?
Slogan: The outermost and left-most nested expression should be evaluated first.
(twice (make-add-suffix "!") "hello")
; (define (f x) ...) is short for (define f (lambda (x) ...)) so,
; = { substitute twice with (lambda (f v) (f (f v)))}
((lambda (f v) (f (f v))) (make-add-suffix "!") "hello")
; = { substition of make-add-suffix with (lambda (s2) (lambda (s) (string-append s s2)))}
((lambda (f v) (f (f v)))
((lambda (s2) (lambda (s) (string-append s s2))) "!")
"hello")
Terminology before we move on:
Beta Reduction:
((lambda (x-1 ... x-n) f-body) v-1 ... v-n) == f-body
with all occurrences of x-1 ... x-n
replaced with v-1 ... v-n
, respectively.
Call by Value: The arguments of a function call are evaluated before beta reduction.
; = { beta-reduction of ((lambda (s2) (lambda (s) (string-append s s2))) "!") }
((lambda (f v) (f (f v))) (lambda (s) (string-append s "!")) "hello")
; = { beta-reduction of the whole expression }
((lambda (s) (string-append s "!"))
((lambda (s) (string-append s "!")) "hello"))
; = { beta-reduction of the expression in the argument position first }
((lambda (s) (string-append s "!")) (string-append "hello" "!"))
; ... and the rest is easy:
((lambda (s) (string-append s "!")) "hello!")
(string-append "hello!" "!")
"hello!!"