结果表达式参数重复时能否用通配符匿名函数?Scala平方报错解析
问题1:当结果表达式中存在重复参数时,能否使用通配符匿名函数?
答案是不能。Scala里的通配符_在匿名函数中是按位置绑定参数的,每个_对应函数的一个独立参数位置,而不是同一个参数的重复引用。
举个实际的例子:如果你想实现“输入一个整数,返回它的平方”,用占位符写的(_:Int)*(_:Int)会被编译器解析成一个需要两个Int参数的函数(也就是Function2[Int, Int, Int]),而非复用同一个参数的单参数函数。这意味着你没办法用占位符语法来表达“同一个参数重复使用”的逻辑——因为每个_都代表不同的输入位置。
问题2:为什么用占位符写平方函数会报错?内部发生了什么?
我们来拆解两种写法的底层解析逻辑:
普通匿名函数写法:
var square = (x:Int) => x*x这里编译器明确识别出这是一个
Function1[Int, Int](单参数函数):参数x被定义一次,在表达式x*x中被复用了两次。调用square(3)时,x被替换为3,计算3*3得到9,完全符合预期。占位符写法:
var square = (_:Int)*(_:Int)这里的每个
_都是独立的参数占位符。Scala的规则是:表达式中有n个_,就会被解析成接受n个参数的函数。这里有两个_,所以编译器会把它推断为Function2[Int, Int, Int]——也就是需要传入两个Int参数,分别对应第一个_和第二个_,然后返回它们的乘积。当你调用
square(3)时,只传入了一个参数,编译器自然会报错:Not enough arguments for method apply: (v1: Int, v2: Int)Int in trait Function2. Unspecified value parameter v2。因为它期望你传入两个参数(比如square(3,4)会返回12),但这显然不是你想要的平方逻辑。
本质上,占位符的_是“按位置数个数”的,不是“按名字复用”的,这就是两种写法产生差异的核心原因。
内容的提问来源于stack exchange,提问作者NSH

