简体   繁体   中英

Order of the evaluation of lambda expressions in Scheme

Dr. Racket user.

Here are two expressions:

((lambda(x)(+ x 1))3)

((lambda(x)(+ x 1)2)3)

The first is a lambda expression that takes one input and increases it by 1. So it takes 3 as its operand and makes (lambda(3)(+ 3 1) which is equal to 4.

The second one is very ambiguous to me since it evaluates to 2 and I can't understand the order of its evaluation. I know that it has to do something with the brackets which change the order but I can't understand how. Obviously it doesn't even sum "the 1" and "the x" just for some reason producing 2 as the output. I miss some basic understanding of the evaluation. Thanks in advance!

As stated in Racket docs :

A function definition can include multiple expressions for the function's body. In that case, only the value of the last expression is returned when the function is called. The other expressions are evaluated only for some side-effect, such as printing.

For example:

(define (f x)
  (+ 1 1)              ;; evaluates to 2, but not returned    
  (= 3 4)              ;; evaluates to false, but not returned
  0                    ;; evaluates to 0, but not returned
  1000                 ;; evaluates to 1000, but not returned
  pi                   ;; evaluates to pi, but not returned
  "I am a string")     ;; last expression; evaluates and returns "I am a string"

and

(f 10)
=> "I am a string"
(f 'okay)
=> "I am a string"
(f pi)
=> "I am a string"

The same thing is happening in your last lambda, whereby:

((lambda (x) (+ x 1) 2) 3)
=> ((lambda () (+ 3 1) 2))
=> ((lambda () 4 2))   ;; last expression is 2, so output 2
=> 2

The body of all derived forms from lambda is evaluated from left to right in order as in a begin . All but the last expression are only evaluated for side effect while the result of the very last expression will be the result of your function:

((lambda (x)
   (+ x 1) ; not in tail position. no effect so it's dead code
   2)      ; the evaluation of 2 will be the result every time
 3) ; argument, only used by dead code.

It actually does produce the sum, then throw it away to evaluate the last expression. Only good use for dead code is keeping warm in the winter. An example of a more sensible use of more expressions in the body:

(define (hypopotemus a b)
  (define (square x)                ; Not in tail position, creates 
    (* x x))                        ; a function as side effect.
  (sqrt (+ (square a) (square b)))) ; Tail expression calculates the result

And since this mentions evaluation order. While arguments to functions are evaluated strictly left to right in #lang racket in all the the Scheme reports, like #!r6rs , an implementation (like racket) can choose any order. eg.

((lambda (a b c) (display "d")) 
 (display "a")
 (display "b")
 (display "c")

While the above code always prints "abcd" in #lang racket it is only one of 6 possible outcomes in Scheme since you don't know which order the arguments are evaluated first, middle and last and the printing will happen in evaluating order. I know racket of course evaluates their Scheme code left to right while Ikarus does it ion the opposite order.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM