简体   繁体   English

Scheme中lambda表达式的评估顺序

[英]Order of the evaluation of lambda expressions in Scheme

Dr. Racket user. Dr. Racket用户。

Here are two expressions: 这有两个表达式:

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

((lambda(x)(+ x 1)2)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. 第一个是lambda表达式,它接受一个输入并将其增加1.因此它需要3作为其操作数并使(lambda(3)(+ 3 1)等于4。

The second one is very ambiguous to me since it evaluates to 2 and I can't understand the order of its evaluation. 第二个对我来说非常模棱两可,因为它评估为2,我无法理解其评估的顺序。 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. 显然它甚至没有将“1”和“x”加起来只是出于某种原因产生2作为输出。 I miss some basic understanding of the evaluation. 我错过了对评估的一些基本了解。 Thanks in advance! 提前致谢!

As stated in Racket docs : 如Racket 文档中所述

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中发生了同样的事情,其中​​:

((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 . 从所有衍生形式本体lambda从左至右,以便如在评价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. 虽然函数的参数在所有Scheme报告中的#lang racket中严格从左到右进行评估,例如#!r6rs ,但实现(如racket)可以选择任何顺序。 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. 虽然上面的代码总是在#lang racket打印“abcd”,但它只是Scheme中6种可能结果中的一种,因为你不知道参数在第一个,中间和最后被评估的顺序,并且打印将在评估顺序中发生。 I know racket of course evaluates their Scheme code left to right while Ikarus does it ion the opposite order. 我知道球拍当然会从左到右评估他们的方案代码,而Ikarus则按照相反的顺序进行评估。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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