Scala 中下划线的所有用途是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8000903/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are all the uses of an underscore in Scala?
提问by Ivan
I've taken a look at the listof surveys taken on scala-lang.organd noticed a curious question: "Can you name all the uses of “_”?". Can you? If yes, please do so here. Explanatory examples are appreciated.
我查看了scala-lang.org上的调查列表,注意到一个奇怪的问题:“你能说出“_”的所有用法吗?”。你可以吗?如果是,请在此处进行。解释性的例子表示赞赏。
回答by Owen
The ones I can think of are
我能想到的有
Existential types
存在类型
def foo(l: List[Option[_]]) = ...
Higher kinded type parameters
更高级的类型参数
case class A[K[_],T](a: K[T])
Ignored variables
忽略的变量
val _ = 5
Ignored parameters
忽略的参数
List(1, 2, 3) foreach { _ => println("Hi") }
Ignored names of self types
忽略自身类型的名称
trait MySeq { _: Seq[_] => }
Wildcard patterns
通配符模式
Some(5) match { case Some(_) => println("Yes") }
Wildcard patterns in interpolations
插值中的通配符模式
"abc" match { case s"a$_c" => }
Sequence wildcard in patterns
模式中的序列通配符
C(1, 2, 3) match { case C(vs @ _*) => vs.foreach(f(_)) }
Wildcard imports
通配符导入
import java.util._
Hiding imports
隐藏进口
import java.util.{ArrayList => _, _}
Joining letters to operators
加入给运营商的信
def bang_!(x: Int) = 5
Assignment operators
赋值运算符
def foo_=(x: Int) { ... }
Placeholder syntax
占位符语法
List(1, 2, 3) map (_ + 2)
Method values
方法值
List(1, 2, 3) foreach println _
Converting call-by-name parameters to functions
将按名称调用的参数转换为函数
def toFunction(callByName: => Int): () => Int = callByName _
Default initializer
默认初始化程序
var x: String = _ // unloved syntax may be eliminated
There may be others I have forgotten!
可能还有其他我忘记了!
Example showing why foo(_)and foo _are different:
显示为什么foo(_)和foo _不同的示例:
This example comes from 0__:
这个例子来自 0__:
trait PlaceholderExample {
def process[A](f: A => Unit)
val set: Set[_ => Unit]
set.foreach(process _) // Error
set.foreach(process(_)) // No Error
}
In the first case, process _represents a method; Scala takes the polymorphic method and attempts to make it monomorphic by filling in the type parameter, but realizes that there is no typethat can be filled in for Athat will give the type (_ => Unit) => ?(Existential _is not a type).
在第一种情况下,process _代表一个方法;阶取多晶型的方法和尝试,使其通过在类型参数填充单形,但认识到没有任何类型,可以在对被填充A,这将使类型(_ => Unit) => ?(生存_不是一个类型)。
In the second case, process(_)is a lambda; when writing a lambda with no explicit argument type, Scala infers the type from the argument that foreachexpects, and _ => Unitisa type (whereas just plain _isn't), so it can be substituted and inferred.
在第二种情况下,process(_)是一个 lambda;当编写一个没有显式参数类型的 lambda 时,Scala 从foreach期望的参数推断类型,并且_ => Unit是一个类型(而普通_的不是),所以它可以被替换和推断。
This may well be the trickiest gotcha in Scala I have ever encountered.
这很可能是我在 Scala 中遇到的最棘手的问题。
Note that this example compiles in 2.13. Ignore it like it was assigned to underscore.
请注意,此示例在 2.13 中编译。忽略它,就像它被分配给下划线一样。
回答by Daniel C. Sobral
From (my entry) in the FAQ, which I certainly do not guarantee to be complete (I added two entries just two days ago):
来自FAQ中的(我的条目),我当然不保证它是完整的(我两天前添加了两个条目):
import scala._ // Wild card -- all of Scala is imported
import scala.{ Predef => _, _ } // Exception, everything except Predef
def f[M[_]] // Higher kinded type parameter
def f(m: M[_]) // Existential type
_ + _ // Anonymous function placeholder parameter
m _ // Eta expansion of method into method value
m(_) // Partial function application
_ => 5 // Discarded parameter
case _ => // Wild card pattern -- matches anything
val (a, _) = (1, 2) // same thing
for (_ <- 1 to 10) // same thing
f(xs: _*) // Sequence xs is passed as multiple parameters to f(ys: T*)
case Seq(xs @ _*) // Identifier xs is bound to the whole matched sequence
var i: Int = _ // Initialization to the default value
def abc_<>! // An underscore must separate alphanumerics from symbols on identifiers
t._2 // Part of a method name, such as tuple getters
1_000_000 // Numeric literal separator (Scala 2.13+)
This is also part of this question.
这也是这个问题的一部分。
回答by JAiro
An excellent explanation of the uses of the underscore is Scala _ [underscore] magic.
对下划线使用的一个很好的解释是Scala _ [underscore] magic。
Examples:
例子:
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "anything other than one and two"
}
expr match {
case List(1,_,_) => " a list with three element and the first element is 1"
case List(_*) => " a list with zero or more elements "
case Map[_,_] => " matches a map with any key type and any value type "
case _ =>
}
List(1,2,3,4,5).foreach(print(_))
// Doing the same without underscore:
List(1,2,3,4,5).foreach( a => print(a))
In Scala, _acts similar to *in Java while importing packages.
在 Scala 中,导入包时的_行为类似于*Java。
// Imports all the classes in the package matching
import scala.util.matching._
// Imports all the members of the object Fun (static import in Java).
import com.test.Fun._
// Imports all the members of the object Fun but renames Foo to Bar
import com.test.Fun.{ Foo => Bar , _ }
// Imports all the members except Foo. To exclude a member rename it to _
import com.test.Fun.{ Foo => _ , _ }
In Scala, a getter and setter will be implicitly defined for all non-private vars in a object. The getter name is same as the variable name and _=is added for the setter name.
在 Scala 中,将为对象中的所有非私有变量隐式定义 getter 和 setter。getter 名称与变量名称相同,并_=为 setter 名称添加。
class Test {
private var a = 0
def age = a
def age_=(n:Int) = {
require(n>0)
a = n
}
}
Usage:
用法:
val t = new Test
t.age = 5
println(t.age)
If you try to assign a function to a new variable, the function will be invoked and the result will be assigned to the variable. This confusion occurs due to the optional braces for method invocation. We should use _ after the function name to assign it to another variable.
如果您尝试将函数分配给新变量,则会调用该函数并将结果分配给该变量。这种混淆是由于方法调用的可选大括号造成的。我们应该在函数名后使用 _ 将其分配给另一个变量。
class Test {
def fun = {
// Some code
}
val funLike = fun _
}
回答by Electric Coffee
There is one usage I can see everyone here seems to have forgotten to list...
有一种用法我看到这里的每个人似乎都忘记列出......
Rather than doing this:
而不是这样做:
List("foo", "bar", "baz").map(n => n.toUpperCase())
You could can simply do this:
你可以简单地这样做:
List("foo", "bar", "baz").map(_.toUpperCase())
回答by swaraj patil
Here are some more examples where _is used:
以下_是使用的更多示例:
val nums = List(1,2,3,4,5,6,7,8,9,10)
nums filter (_ % 2 == 0)
nums reduce (_ + _)
nums.exists(_ > 5)
nums.takeWhile(_ < 8)
In all above examples one underscore represents an element in the list (for reduce the first underscore represents the accumulator)
在以上所有示例中,一个下划线表示列表中的一个元素(为了减少第一个下划线表示累加器)
回答by tolitius
Besides the usagesthat JAiro mentioned, I like this one:
除了JAiro提到的用法,我喜欢这个:
def getConnectionProps = {
( Config.getHost, Config.getPort, Config.getSommElse, Config.getSommElsePartTwo )
}
If someone needs all connection properties, he can do:
如果有人需要所有连接属性,他可以这样做:
val ( host, port, sommEsle, someElsePartTwo ) = getConnectionProps
If you need just a host and a port, you can do:
如果你只需要一个主机和一个端口,你可以这样做:
val ( host, port, _, _ ) = getConnectionProps
回答by Ke.Steve
There is a specific example that "_" be used:
有一个使用“_”的具体示例:
type StringMatcher = String => (String => Boolean)
def starts: StringMatcher = (prefix:String) => _ startsWith prefix
may be equal to :
可能等于:
def starts: StringMatcher = (prefix:String) => (s)=>s startsWith prefix
Applying “_” in some scenarios will automatically convert to “(x$n) => x$n ”
在某些情况下应用“_”会自动转换为“(x$n) => x$n ”

