Scala中使用val定义函数字面量的代码示例解析
解析Scala中两种val定义函数字面量的行为差异
让我结合你给出的Scala交互代码,拆解这两种函数字面量定义的执行逻辑和行为差异:
scala> val double = (i: Int) => { | println("I am here") | i * 2 | } double: Int => Int = $$Lambda$1090/773348080@6ae9b2f0 scala> double(4) I am here res22: Int = 8 scala> val evenFunc: (Int => Boolean) = { | println("I am here"); | (x => x % 2 == 0) | } I am here evenFunc: Int => Boolean = $$Lambda$1091/373581540@a7c489a scala> double res23: Int => Int = $$Lambda$1090/773348080@6ae9b2f0 scala> evenFunc res24: Int => Boolean = $$Lambda$1091/...
1. 第一种:直接赋值匿名函数字面量 (val double = (i: Int) => { ... })
这种写法是把一个匿名函数字面量直接绑定到变量double。这里的花括号是函数字面量的函数体,里面的代码只有在调用这个函数的时候才会触发执行:
- 当你定义
double时,Scala只是创建了一个实现Int => Inttrait的Lambda实例,函数体里的println("I am here")和i * 2都不会执行,所以定义阶段没有任何控制台输出。 - 只有当你调用
double(4)时,才会进入函数体执行逻辑:先打印"I am here",再计算4 * 2并返回结果,这时候你才会看到输出,同时得到返回值8。
2. 第二种:代码块返回函数字面量 (val evenFunc: (Int => Boolean) = { ... })
这种写法的右边是一个普通的Scala代码块,而不是直接的函数字面量。这个代码块会在变量初始化(也就是定义evenFunc的瞬间)立即执行,代码块的最后一行表达式的结果会被赋值给evenFunc:
- 当你定义
evenFunc时,Scala会先执行代码块里的所有语句:先打印"I am here",然后执行最后一行的(x => x % 2 == 0)创建一个Lambda实例,把这个实例赋值给evenFunc。所以定义阶段就直接输出了"I am here"。 - 之后你调用
evenFunc(比如evenFunc(2))时,只会执行这个Lambda的核心逻辑(判断输入是否为偶数),不会再执行之前的打印语句——因为打印语句是初始化代码块的一部分,在变量定义时就已经执行完毕了。
核心差异总结
- 执行时机不同:
- 第一种定义:函数体代码仅在调用
double(参数)时执行,定义变量时不会触发。 - 第二种定义:代码块在
evenFunc初始化时立即执行,后续调用函数不会再触发这段初始化代码。
- 第一种定义:函数体代码仅在调用
- 代码块的角色不同:
- 第一种的花括号是函数字面量的一部分,属于函数被调用时要执行的核心逻辑。
- 第二种的花括号是独立的初始化代码块,它的作用是生成最终要赋值给变量的函数字面量,代码块里的其他语句(比如
println)都是初始化时产生的副作用。
内容的提问来源于stack exchange,提问作者Mandroid
相关产品推荐
相关产品推荐

