ฉันได้ดูคำถามนี้แล้วแต่ยังไม่เข้าใจความแตกต่างระหว่างลักษณะที่สามารถทำซ้ำได้และลักษณะที่ผ่านได้ ใครช่วยอธิบายหน่อย
ฉันได้ดูคำถามนี้แล้วแต่ยังไม่เข้าใจความแตกต่างระหว่างลักษณะที่สามารถทำซ้ำได้และลักษณะที่ผ่านได้ ใครช่วยอธิบายหน่อย
คำตอบ:
พูดง่ายๆก็คือตัววนซ้ำจะรักษาสถานะการข้ามผ่านไม่ได้
A Traversableมีวิธีนามธรรมอย่างหนึ่ง: foreach. เมื่อคุณโทรforeach, คอลเลกชันจะฟีดฟังก์ชั่นผ่านองค์ประกอบทั้งหมดที่จะช่วยให้คนหนึ่งหลังจากที่อื่น ๆ
ในทางกลับกันวิธีIterablehas as abstract iteratorซึ่งส่งกลับค่าIterator. คุณสามารถโทรnextหาIteratorเพื่อรับองค์ประกอบถัดไปในเวลาที่คุณเลือก คุณต้องติดตามว่ามันอยู่ที่ใดในคอลเลกชันและมีอะไรต่อไป
IterableขยายออกไปTraversableดังนั้นฉันเดาว่าคุณหมายถึงTraversables นั่นไม่ใช่Iterables
Traversableอินเทอร์เฟซไม่จำเป็นต้องมีการรักษาสถานะในขณะที่ปฏิบัติตามIteratorอินเทอร์เฟซ
Traversables ที่Iterableไม่คงสถานะการวนซ้ำใด ๆ เป็นสิ่งที่Iteratorสร้างและส่งคืนโดยสิ่งIterableที่รักษาสถานะ
คิดว่ามันเป็นความแตกต่างระหว่างการเป่าและการดูด
เมื่อคุณโทรหาTraversablesforeachหรือเมธอดที่ได้รับมามันจะระเบิดค่าในฟังก์ชันของคุณทีละฟังก์ชันดังนั้นจึงมีการควบคุมการวนซ้ำ
ด้วยการIteratorส่งคืนโดยIterableแม้ว่าคุณจะดูดค่าออกจากมันและควบคุมว่าเมื่อใดที่จะย้ายไปยังค่าถัดไปด้วยตัวคุณเอง
TL; DR Iterablesอยู่Traversablesที่สามารถผลิต statefulIterators
ขั้นแรกให้รู้ว่าIterableเป็นลบของTraversableของ
ประการที่สอง
Traversableต้องใช้foreachวิธีการซึ่งใช้โดยทุกสิ่งทุกอย่าง
Iterableต้องใช้iteratorวิธีการซึ่งใช้โดยทุกสิ่งทุกอย่าง
ตัวอย่างเช่นการดำเนินการfindสำหรับการTraversableใช้งานforeach(ผ่าน a เพื่อความเข้าใจ) และแสดงBreakControlข้อยกเว้นเพื่อหยุดการทำซ้ำเมื่อพบองค์ประกอบที่น่าพอใจ
trait TravserableLike {
def find(p: A => Boolean): Option[A] = {
var result: Option[A] = None
breakable {
for (x <- this)
if (p(x)) { result = Some(x); break }
}
result
}
}
ในทางตรงกันข้ามการIterableลบจะลบล้างการใช้งานนี้และเรียกfindใช้Iteratorซึ่งจะหยุดการทำซ้ำเมื่อพบองค์ประกอบ:
trait Iterable {
override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
iterator.find(p)
}
trait Iterator {
def find(p: A => Boolean): Option[A] = {
var res: Option[A] = None
while (res.isEmpty && hasNext) {
val e = next()
if (p(e)) res = Some(e)
}
res
}
}
จะเป็นการดีที่จะไม่ทิ้งข้อยกเว้นสำหรับTraversableการทำซ้ำ แต่นั่นเป็นวิธีเดียวที่จะวนซ้ำบางส่วนเมื่อใช้เพียงforeachแต่นั่นเป็นวิธีเดียวที่จะย้ำบางส่วนเมื่อใช้เพียง
จากมุมมองหนึ่งIterableคือการเรียกร้องมากขึ้น / ลักษณะที่มีประสิทธิภาพในขณะที่คุณสามารถดำเนินการforeachโดยใช้iteratorแต่คุณไม่สามารถจริงๆดำเนินการโดยใช้iteratorforeach
โดยสรุปIterableมีวิธีที่จะหยุดชั่วคราวหรือหยุดย้ำผ่าน Iteratorstateful ด้วยTraversableมันทั้งหมดหรือไม่มีอะไร (ยกเว้นซองสำหรับการควบคุมการไหล)
โดยส่วนใหญ่ไม่สำคัญและคุณจะต้องการอินเทอร์เฟซที่กว้างขึ้น แต่ถ้าคุณต้องการการควบคุมการทำซ้ำแบบกำหนดเองมากขึ้นคุณจะต้องมีIteratorซึ่งคุณสามารถเรียกดูได้จากIterableไฟล์.
คำตอบของแดเนียลฟังดูดี ขอดูว่าจะใส่คำพูดของตัวเองได้ไหม
ดังนั้น Iterable สามารถให้คุณทำซ้ำซึ่งช่วยให้คุณสำรวจองค์ประกอบทีละรายการ (โดยใช้ next ()) และหยุดและไปตามที่คุณต้องการ ในการทำเช่นนั้นตัววนซ้ำจำเป็นต้องให้ "ตัวชี้" ภายในอยู่ในตำแหน่งขององค์ประกอบ แต่ Traversable ช่วยให้คุณมีวิธี foreach เพื่อสำรวจองค์ประกอบทั้งหมดพร้อมกันโดยไม่หยุด
บางอย่างเช่น Range (1, 10) จำเป็นต้องมีจำนวนเต็ม 2 จำนวนเท่านั้นที่เป็นสถานะ Traversable แต่ช่วง (1, 10) เป็นตัวทำซ้ำได้จะทำให้คุณมีตัวทำซ้ำซึ่งจำเป็นต้องใช้จำนวนเต็ม 3 ตัวสำหรับสถานะซึ่งหนึ่งในนั้นคือดัชนี
เมื่อพิจารณาว่า Traversable ยังมี foldLeft, foldRight ซึ่ง foreach จำเป็นต้องสำรวจองค์ประกอบตามลำดับที่ทราบและคงที่ ดังนั้นจึงเป็นไปได้ที่จะใช้ตัววนซ้ำสำหรับ Traversable เช่น def iterator = toList.iterator
TraversableในScala 2.13 (ยังคงถูกเก็บไว้เป็นนามแฝงที่เลิกใช้งานIterableจนถึง 2.14)