Scala 语法有很多符号。由于使用搜索引擎很难找到这些类型的名称,因此它们的完整列表会有所帮助。
Scala 中的所有符号是什么,每个符号的作用是什么?
特别想知道->, ||=, ++=, <=, _._, ::, 和:+=。
->
||=
++=
<=
_._
::
:+=
出于教学的目的,我将运算符分为 四类 :
幸运的是,大多数类别都出现在问题中:
-> // 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类上的方法。
Int
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
快速查看内部Predef显示一些符号:
class <:< class =:= object <%< object =:=
任何其他符号都将通过 隐式转换 变得可用。只需查看标记为implicit接收方法的方法,作为参数,接收该方法的类型的对象。例如:
implicit
"a" -> 1 // Look for an implicit from String, AnyRef, Any or type parameter
在上述情况下,是通过接受类型对象的方法->在类中定义的,其中是同一方法的无界类型参数。ArrowAssocany2ArrowAssoc``A``A
ArrowAssoc
any2ArrowAssoc``A``A
因此,许多符号只是类上的方法。例如,如果你这样做
List(1, 2) ++ List(3, 4)
您可以++在 ScalaDoc 的List中找到该方法。但是,在搜索方法时必须注意一个约定。以冒号 ( :) 结尾的方法绑定 到右侧 而不是左侧。也就是说,虽然上面的方法调用等价于:
++
:
List(1, 2).++(List(3, 4))
相反1 :: List(2, 3),如果我有,那将相当于:
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.