Я ділю операторів з метою викладання на чотири категорії :
- Ключові слова / зарезервовані символи
- Автоматично імпортні методи
- Загальні методи
- Синтаксичні цукру / склад
Тоді щастить, що більшість категорій представлені у питанні:
-> // 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
Точне значення більшості цих методів залежить від класу, який їх визначає. Наприклад, <=
на 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 Specification (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
У наведеному вище випадку ->
визначається в класі ArrowAssoc
за допомогою методу, any2ArrowAssoc
який приймає об'єкт типу A
, де A
параметр необмеженого типу до того ж методу.
Загальні методи
Отже, багато символів - це просто методи на уроці. Наприклад, якщо це зробити
List(1, 2) ++ List(3, 4)
Ви знайдете метод ++
прямо у ScalaDoc for List . Однак є одна умова, якої ви повинні знати, шукаючи методи. Методи, що закінчуються двокрапкою ( :
), пов'язують праворуч, а не ліворуч. Іншими словами, хоча виклик вищевказаного методу еквівалентний:
List(1, 2).++(List(3, 4))
Якби я, замість цього 1 :: List(2, 3)
, це було б рівнозначно:
List(2, 3).::(1)
Тому потрібно шукати тип, знайдений праворуч, шукаючи методи, що закінчуються двокрапкою. Розглянемо, наприклад:
1 +: List(2, 3) :+ 4
Перший метод ( +:
) пов'язує праворуч і знаходиться на List
. Другий метод ( :+
) - це просто звичайний метод, і пов'язується зліва - знову ж таки 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.