ฉันได้ดูคำถามนี้แล้วแต่ยังไม่เข้าใจความแตกต่างระหว่างลักษณะที่สามารถทำซ้ำได้และลักษณะที่ผ่านได้ ใครช่วยอธิบายหน่อย
ฉันได้ดูคำถามนี้แล้วแต่ยังไม่เข้าใจความแตกต่างระหว่างลักษณะที่สามารถทำซ้ำได้และลักษณะที่ผ่านได้ ใครช่วยอธิบายหน่อย
คำตอบ:
พูดง่ายๆก็คือตัววนซ้ำจะรักษาสถานะการข้ามผ่านไม่ได้
A Traversable
มีวิธีนามธรรมอย่างหนึ่ง: foreach
. เมื่อคุณโทรforeach
, คอลเลกชันจะฟีดฟังก์ชั่นผ่านองค์ประกอบทั้งหมดที่จะช่วยให้คนหนึ่งหลังจากที่อื่น ๆ
ในทางกลับกันวิธีIterable
has as abstract iterator
ซึ่งส่งกลับค่าIterator
. คุณสามารถโทรnext
หาIterator
เพื่อรับองค์ประกอบถัดไปในเวลาที่คุณเลือก คุณต้องติดตามว่ามันอยู่ที่ใดในคอลเลกชันและมีอะไรต่อไป
Iterable
ขยายออกไปTraversable
ดังนั้นฉันเดาว่าคุณหมายถึงTraversable
s นั่นไม่ใช่Iterable
s
Traversable
อินเทอร์เฟซไม่จำเป็นต้องมีการรักษาสถานะในขณะที่ปฏิบัติตามIterator
อินเทอร์เฟซ
Traversable
s ที่Iterable
ไม่คงสถานะการวนซ้ำใด ๆ เป็นสิ่งที่Iterator
สร้างและส่งคืนโดยสิ่งIterable
ที่รักษาสถานะ
คิดว่ามันเป็นความแตกต่างระหว่างการเป่าและการดูด
เมื่อคุณโทรหาTraversable
sforeach
หรือเมธอดที่ได้รับมามันจะระเบิดค่าในฟังก์ชันของคุณทีละฟังก์ชันดังนั้นจึงมีการควบคุมการวนซ้ำ
ด้วยการ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
แต่คุณไม่สามารถจริงๆดำเนินการโดยใช้iterator
foreach
โดยสรุปIterable
มีวิธีที่จะหยุดชั่วคราวหรือหยุดย้ำผ่าน Iterator
stateful ด้วย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)