You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala中部分应用函数里下划线与占位符的区别

理解Scala中下划线的两种核心用法:方法转函数 vs 参数占位符

嘿,这个问题我当初刚学Scala的时候也纠结了好久!咱们把这两个例子拆开,一步步搞清楚它们的本质~

一、someNumbers.foreach(println _):方法转函数的ETA展开

首先要明确:println是方法(def定义的),而foreach方法需要的参数是一个函数值(比如Int => Unit类型)。这里的下划线_不是单个参数的占位符,而是Scala里的ETA展开标记——它的作用是把整个println方法“打包”成一个和它参数列表匹配的函数,直接传递给foreach。

和普通参数占位符的区别

如果写成someNumbers.foreach(println(_)),这里的下划线是单个参数的占位符,相当于你手动写了一个匿名函数:

someNumbers.foreach(x => println(x))

而println _是直接把方法转换成函数,相当于告诉Scala:“把这个println方法变成一个可以直接作为参数传递的函数”。虽然这两种写法在这个场景下效果一样,但本质不同:

  • println(_)是创建了一个新的匿名函数,内部调用println方法;
  • println _是直接将原方法转换为函数值,没有额外的匿名函数包装。

二、val addFunction = add _:同一概念的另一种场景

完全是同一个概念!add是一个方法(def add(x: Int, y: Int) = x + y),而addFunction是一个函数值(类型为(Int, Int) => Int,也就是Scala内置的Function2[Int, Int, Int])。

这里的下划线同样是ETA展开标记,作用是把方法add转换成对应的函数类型,让它可以被赋值给变量。它等价于手动写匿名函数:

val addFunction = (x: Int, y: Int) => add(x, y)

你可以理解为:下划线在这里“替代了整个参数列表”,告诉Scala“按照原方法的参数列表,生成一个对应的函数”。

总结两种下划线用法的核心差异

  • 方法转函数(ETA展开):方法名 _,下划线代表整个参数列表的占位,用于把def定义的方法转换成可以赋值、传递的函数值;
  • 匿名函数参数占位符:_(单个或多个),每个下划线对应匿名函数的一个参数,按顺序匹配,比如list.map(_ * 2)等价于list.map(x => x * 2),(a, b) => a + b可以简写为_ + _。

额外补充:Scala有时候会自动做ETA展开,比如someNumbers.foreach(println)不用下划线也能运行,因为编译器能推断出需要把方法转成函数。但在赋值给变量的场景(比如val f = add _),必须加下划线,否则编译器会报错——因为方法不能直接赋值给变量,必须先转成函数值。

内容的提问来源于stack exchange,提问作者Jwan622

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:00:14