หนึ่งในคุณสมบัติใหม่ของ Scala 2.8 คือขอบเขตบริบท บริบทที่ผูกไว้คืออะไรและมีประโยชน์ที่ใด
แน่นอนฉันค้นหาก่อน (และพบเช่นนี้ ) แต่ฉันไม่พบข้อมูลที่ชัดเจนและละเอียดมาก
หนึ่งในคุณสมบัติใหม่ของ Scala 2.8 คือขอบเขตบริบท บริบทที่ผูกไว้คืออะไรและมีประโยชน์ที่ใด
แน่นอนฉันค้นหาก่อน (และพบเช่นนี้ ) แต่ฉันไม่พบข้อมูลที่ชัดเจนและละเอียดมาก
คำตอบ:
คุณพบบทความนี้หรือไม่? ครอบคลุมคุณลักษณะบริบทใหม่ที่ถูกผูกไว้ภายในบริบทของการปรับปรุงอาร์เรย์
โดยทั่วไปพารามิเตอร์ชนิดที่มีบริบทที่ถูกผูกไว้เป็นของแบบฟอร์ม[T: Bound]
; มันจะขยายไปยังประเภทธรรมดาพารามิเตอร์ร่วมกับพารามิเตอร์โดยนัยของประเภท T
Bound[T]
พิจารณาวิธีการtabulate
ที่สร้างอาร์เรย์จากผลลัพธ์ของการใช้ฟังก์ชันที่กำหนด f ในช่วงของตัวเลขตั้งแต่ 0 จนถึงความยาวที่กำหนด มากถึง Scala 2.7 ตารางสามารถเขียนได้ดังนี้:
def tabulate[T](len: Int, f: Int => T) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
ใน Scala 2.8 เป็นไปไม่ได้อีกต่อไปเนื่องจากข้อมูลรันไทม์เป็นสิ่งที่จำเป็นในการสร้างการแสดงที่ถูกต้องของArray[T]
. เราจำเป็นต้องให้ข้อมูลนี้โดยส่งผ่าน a ClassManifest[T]
เข้าไปใน method เป็นพารามิเตอร์โดยปริยาย:
def tabulate[T](len: Int, f: Int => T)(implicit m: ClassManifest[T]) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
ในรูปแบบชวเลขสามารถใช้บริบทขอบเขตกับพารามิเตอร์ type T
แทนโดยให้:
def tabulate[T: ClassManifest](len: Int, f: Int => T) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
คำตอบของโรเบิร์ตครอบคลุมรายละเอียดทางเทคนิคของขอบเขตบริบท ฉันจะให้คุณตีความความหมายของมัน
ใน Scala a View Bound ( A <% B
) รวบรวมแนวคิดของ 'can be seen as' (ในขณะที่ขอบเขตด้านบน<:
รวบรวมแนวคิดของ 'is a') บริบทที่ถูกผูกไว้ ( A : C
) ระบุว่า 'มี' เกี่ยวกับประเภท คุณสามารถอ่านตัวอย่างเกี่ยวกับรายการที่เป็น " T
มีManifest
" ตัวอย่างที่คุณเชื่อมโยงเกี่ยวกับOrdered
vs Ordering
แสดงให้เห็นถึงความแตกต่าง วิธีการ
def example[T <% Ordered[T]](param: T)
บอกว่าพารามิเตอร์สามารถมองเห็นเป็นOrdered
ไฟล์. เปรียบเทียบกับ
def example[T : Ordering](param: T)
ซึ่งบอกว่าพารามิเตอร์มีการเชื่อมโยง Ordering
ที่บอกว่าพารามิเตอร์มีที่เกี่ยวข้อง
ในแง่ของการใช้งานต้องใช้เวลาสักพักในการสร้างอนุสัญญา แต่ควรใช้ขอบเขตบริบทมากกว่าขอบเขตการดู ( ตอนนี้เลิกใช้งานขอบเขตการดูแล้ว ) ข้อเสนอแนะอย่างหนึ่งคือควรใช้บริบทที่ถูกผูกไว้เมื่อคุณต้องการถ่ายโอนคำจำกัดความโดยนัยจากขอบเขตหนึ่งไปยังอีกขอบเขตหนึ่งโดยไม่จำเป็นต้องอ้างถึงโดยตรง (แน่นอนว่าเป็นกรณีที่ ClassManifest
ใช้ในการสร้างอาร์เรย์)
อีกวิธีหนึ่งในการคิดเกี่ยวกับขอบเขตการดูและขอบเขตบริบทคือการถ่ายโอนการแปลงโดยนัยจากขอบเขตของผู้โทรครั้งแรก สิ่งที่สองถ่ายโอนวัตถุโดยนัยจากขอบเขตของผู้โทร
has a
เหมาะสมกับฉันมากขึ้น]
(นี่คือบันทึกย่อโปรดอ่านและทำความเข้าใจคำตอบอื่น ๆ ก่อน)
ขอบเขตบริบททำให้เกิดขอบเขตการดูโดยทั่วไป
ดังนั้นให้รหัสนี้แสดงด้วย View Bound:
scala> implicit def int2str(i: Int): String = i.toString
int2str: (i: Int)String
scala> def f1[T <% String](t: T) = 0
f1: [T](t: T)(implicit evidence$1: (T) => String)Int
นอกจากนี้ยังอาจจะแสดงออกกับบริบทที่ถูกผูกไว้ด้วยความช่วยเหลือของนามแฝงประเภทที่เป็นตัวแทนของฟังก์ชั่นจากประเภทประเภทF
T
scala> trait To[T] { type From[F] = F => T }
defined trait To
scala> def f2[T : To[String]#From](t: T) = 0
f2: [T](t: T)(implicit evidence$1: (T) => java.lang.String)Int
scala> f2(1)
res1: Int = 0
* => *
บริบทผูกพันต้องใช้กับตัวสร้างประเภทของชนิด อย่างไรก็ตามประเภทสร้างเป็นของชนิดFunction1
(*, *) => *
การใช้นามแฝงประเภทบางส่วนใช้พารามิเตอร์ประเภทที่สองกับประเภทString
โดยให้ตัวสร้างชนิดที่ถูกต้องเพื่อใช้เป็นขอบเขตบริบท
มีข้อเสนอเพื่อให้คุณสามารถแสดงประเภทที่ใช้บางส่วนใน Scala ได้โดยตรงโดยไม่ต้องใช้นามแฝงประเภทภายในลักษณะ จากนั้นคุณสามารถเขียน:
def f3[T : [X](X => String)](t: T) = 0
From
To[String]
เราไม่ได้ให้อาร์กิวเมนต์ประเภทFrom
ดังนั้นเราจึงอ้างถึงตัวสร้างประเภทไม่ใช่ประเภท คอนสตรัคชนิดนี้เป็นชนิดที่เหมาะสมที่จะใช้เป็นบริบทผูกพัน * -> *
- นี้ขอบเขตพารามิเตอร์ชนิดโดยกำหนดพารามิเตอร์โดยนัยของประเภทT
To[String]#From[T]
ขยายประเภทนามแฝงและ voila ที่คุณเหลือFunction1[String, T]
อยู่
นี่เป็นบันทึกย่ออื่น
ดังที่Ben ชี้ให้เห็นบริบทที่ถูกผูกไว้แสดงถึงข้อ จำกัด "has-a" ระหว่างพารามิเตอร์ type และคลาส type กล่าวอีกนัยหนึ่งคือแสดงถึงข้อ จำกัด ที่มีค่าโดยนัยของคลาสชนิดเฉพาะ
เมื่อใช้บริบทที่ถูกผูกไว้มักจะต้องแสดงให้เห็นถึงคุณค่าโดยนัยนั้น ตัวอย่างเช่นเมื่อพิจารณาถึงข้อ จำกัดT : Ordering
มักจะต้องมีตัวอย่างOrdering[T]
ที่ตรงตามข้อ จำกัด ดังที่แสดงไว้ที่นี่คุณสามารถเข้าถึงค่าโดยนัยได้โดยใช้implicitly
วิธีการหรือวิธีที่เป็นประโยชน์มากกว่าเล็กน้อยcontext
:
def **[T : Numeric](xs: Iterable[T], ys: Iterable[T]) =
xs zip ys map { t => implicitly[Numeric[T]].times(t._1, t._2) }
หรือ
def **[T : Numeric](xs: Iterable[T], ys: Iterable[T]) =
xs zip ys map { t => context[T]().times(t._1, t._2) }