博士。球拍用户。
这是两个表达式:
((lambda(x)(+ x 1))3)
((lambda(x)(+ x 1)2)3)
第一个是lambda表达式,它接受一个输入并将其增加1.因此它需要3作为其操作数并使(lambda(3)(+ 3 1)等于4。
第二个对我来说非常含糊,因为它评估为2,我无法理解其评估的顺序。我知道它必须用括号改变顺序,但我无法理解。显然,它甚至不能和1" 1"和" x"只是出于某种原因产生2作为输出。我错过了对评估的一些基本了解。提前谢谢!
答案 0 :(得分:6)
如Racket docs中所述:
函数定义可以包含函数体的多个表达式。在这种情况下,调用函数时,仅返回最后一个表达式的值。其他表达式仅针对某些副作用进行评估,例如打印。
例如:
(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"
和
(f 10)
=> "I am a string"
(f 'okay)
=> "I am a string"
(f pi)
=> "I am a string"
同样的事情发生在你的最后一个lambda中,其中:
((lambda (x) (+ x 1) 2) 3)
=> ((lambda () (+ 3 1) 2))
=> ((lambda () 4 2)) ;; last expression is 2, so output 2
=> 2
答案 1 :(得分:1)
来自lambda
的所有派生表单的正文按照从begin
开始的顺序从左到右进行评估。除最后一个表达式之外的所有表达式仅针对副作用进行评估,而最后一个表达式的结果将是您的函数的结果:
((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.
它确实产生了总和,然后扔掉它来评估最后一个表达式。只有善用死码才能在冬天保暖。在身体中更明智地使用更多表情的一个例子:
(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
因为这提到了评估顺序。虽然函数的参数在#lang racket
中在所有Scheme报告中严格从左到右进行评估,例如#!r6rs
,但实现(如球拍)可以选择任何顺序。例如
((lambda (a b c) (display "d"))
(display "a")
(display "b")
(display "c")
虽然上面的代码总是在#lang racket
中打印“abcd”,但它只是其中之一
Scheme中有6种可能的结果,因为您不知道参数在第一,中间和最后评估的顺序,并且打印将在评估顺序中进行。我知道球拍当然会从左到右评估他们的方案代码,而Ikarus则按照相反的顺序进行评估。