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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:38:35  来源:igfitidea点击:

What are all the uses of an underscore in Scala?

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 ”