小编典典

Scala 的所有符号运算符是什么意思?

all

Scala 语法有很多符号。由于使用搜索引擎很难找到这些类型的名称,因此它们的完整列表会有所帮助。

Scala 中的所有符号是什么,每个符号的作用是什么?

特别想知道->, ||=, ++=, <=, _._, ::, 和:+=


阅读 114

收藏
2022-03-21

共1个答案

小编典典

出于教学的目的,我将运算符分为 四类

  • 关键字/保留符号
  • 自动导入的方法
  • 常用方法
  • 语法糖/组合物

幸运的是,大多数类别都出现在问题中:

->    // Automatically imported method
||=   // Syntactic sugar
++=   // Syntactic sugar/composition or common method
<=    // Common method
_._   // Typo, though it's probably based on Keyword/composition
::    // Common method
:+=   // Common method

大多数这些方法的确切含义取决于定义它们的类。例如,<=onInt表示 “小于或等于”
。第一个->,我将在下面给出示例。::可能是定义的方法List(尽管它 可能
是同名的对象),并且:+=可能是定义在各种Buffer类上的方法。

所以,让我们看看他们。

关键字/保留符号

Scala 中有一些特殊的符号。其中两个被认为是正确的关键字,而其他的只是“保留”。他们是:

// Keywords
<-  // Used on for-comprehensions, to separate pattern from generator
=>  // Used for function types, function literals and import renaming

// Reserved
( )        // Delimit expressions and parameters
[ ]        // Delimit type parameters
{ }        // Delimit blocks
.          // Method call and path separator
// /* */   // Comments
#          // Used in type notations
:          // Type ascription or context bounds
<: >: <%   // Upper, lower and view bounds
<? <!      // Start token for various XML elements
" """      // Strings
'          // Indicate symbols and characters
@          // Annotations and variable binding on pattern matching
`          // Denote constant or enable arbitrary identifiers
,          // Parameter separator
;          // Statement separator
_*         // vararg expansion
_          // Many different meanings

这些都是 语言的一部分, 因此,可以在任何正确描述该语言的文本中找到,例如Scala 规范(PDF)
本身。

最后一个,下划线,值得特别描述一下,因为它被广泛使用,并且有很多不同的含义。这是一个示例:

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
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

不过,我可能忘记了其他含义。

自动导入的方法

因此,如果您在上面的列表中没有找到您要查找的符号,那么它一定是一种方法,或者是其中的一部分。但是,通常,您会看到一些符号,并且该类的文档不会包含该方法。发生这种情况时,您正在查看一个或多个方法与其他方法的组合,或者该方法已导入范围,或者可通过导入的隐式转换获得。

这些 仍然可以ScalaDoc上找到:您只需要知道在哪里可以找到它们。或者,如果做不到这一点,请查看索引(目前在
2.9.1 上损坏,但每晚可用)。

每个 Scala 代码都有三个自动导入:

// Not necessarily in this order
import _root_.java.lang._      // _root_ denotes an absolute path
import _root_.scala._
import _root_.scala.Predef._

前两个只使类和单例对象可用。第三个包含所有隐式转换和导入方法,因为Predef它本身就是一个对象。

快速查看内部Predef显示一些符号:

class <:<
class =:=
object <%<
object =:=

任何其他符号都将通过 隐式转换 变得可用。只需查看标记为implicit接收方法的方法,作为参数,接收该方法的类型的对象。例如:

"a" -> 1  // Look for an implicit from String, AnyRef, Any or type parameter

在上述情况下,是通过接受类型对象的方法->在类中定义的,其中是同一方法的无界类型参数。ArrowAssocany2ArrowAssoc``A``A

常用方法

因此,许多符号只是类上的方法。例如,如果你这样做

List(1, 2) ++ List(3, 4)

您可以++在 ScalaDoc 的List中找到该方法。但是,在搜索方法时必须注意一个约定。以冒号
( :) 结尾的方法绑定 到右侧 而不是左侧。也就是说,虽然上面的方法调用等价于:

List(1, 2).++(List(3, 4))

相反1 :: List(2, 3),如果我有,那将相当于:

List(2, 3).::(1)

因此,在查找以冒号结尾的方法时,您需要查看 右侧找到的类型。 例如,考虑:

1 +: List(2, 3) :+ 4

第一个方法 ( +:) 绑定到右侧,并在 上找到List。第二种方法 ( :+) 只是一个普通方法,并且绑定到左侧 - 再次, on
List

语法糖/组合物

所以,这里有一些可能隐藏方法的语法糖:

class Example(arr: Array[Int] = Array.fill(5)(0)) {
  def apply(n: Int) = arr(n)
  def update(n: Int, v: Int) = arr(n) = v
  def a = arr(0); def a_=(v: Int) = arr(0) = v
  def b = arr(1); def b_=(v: Int) = arr(1) = v
  def c = arr(2); def c_=(v: Int) = arr(2) = v
  def d = arr(3); def d_=(v: Int) = arr(3) = v
  def e = arr(4); def e_=(v: Int) = arr(4) = v
  def +(v: Int) = new Example(arr map (_ + v))
  def unapply(n: Int) = if (arr.indices contains n) Some(arr(n)) else None
}

val Ex = new Example // or var for the last example
println(Ex(0))  // calls apply(0)
Ex(0) = 2       // calls update(0, 2)
Ex.b = 3        // calls b_=(3)
// This requires Ex to be a "val"
val Ex(c) = 2   // calls unapply(2) and assigns result to c
// This requires Ex to be a "var"
Ex += 1         // substituted for Ex = Ex + 1

最后一个很有趣,因为 任何 符号方法都可以通过这种方式组合形成类似赋值的方法。

而且,当然,代码中可以出现多种组合:

(_+_) // An expression, or parameter, that is an anonymous function with
      // two parameters, used exactly where the underscores appear, and
      // which calls the "+" method on the first parameter passing the
      // second parameter as argument.
2022-03-21