ฉันแบ่งผู้ปฏิบัติงานเพื่อวัตถุประสงค์ในการสอนเป็นสี่ประเภท :
- คำหลัก / สัญลักษณ์ที่สงวนไว้
- วิธีการนำเข้าโดยอัตโนมัติ
- วิธีการทั่วไป
- น้ำตาล / องค์ประกอบของวากยสัมพันธ์
โชคดีที่หมวดหมู่ส่วนใหญ่มีคำถาม:
-> // 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 แต่มีให้ทุกคืน)
รหัสสกาล่าทุกตัวมีการนำเข้าอัตโนมัติสามรายการ:
// 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 สำหรับรายการ อย่างไรก็ตามมีการประชุมหนึ่งข้อที่คุณต้องระวังเมื่อค้นหาวิธีต่างๆ วิธีการที่ลงท้ายด้วยโคลอน ( :
) ผูกทางด้านขวาแทนด้านซ้าย กล่าวอีกนัยหนึ่งขณะที่การเรียกเมธอดด้านบนเทียบเท่ากับ:
List(1, 2).++(List(3, 4))
หากฉันมี1 :: List(2, 3)
สิ่งนั้นจะเทียบเท่ากับ:
List(2, 3).::(1)
ดังนั้นคุณต้องดูประเภทที่พบทางด้านขวาเมื่อค้นหาวิธีที่ลงท้ายด้วยเครื่องหมายโคลอน ยกตัวอย่างเช่น
1 +: List(2, 3) :+ 4
วิธีแรก ( +:
) List
ผูกไปทางขวาและสามารถพบได้ใน วิธีที่สอง ( :+
) เป็นเพียงวิธีการปกติและผูกไปทางซ้าย - List
อีกครั้งใน
น้ำตาล / องค์ประกอบของวากยสัมพันธ์
ดังนั้นนี่คือน้ำตาล syntactic น้ำตาลที่อาจซ่อนวิธี:
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.