นักพัฒนา Ruby ทุกคนเรียนรู้ตั้งแต่เนิ่นๆ เกี่ยวกับแนวคิดของ “การแจงนับ” ซึ่งใช้เพื่ออ้างถึงชิ้นส่วนของข้อมูลที่ทำซ้ำได้ (ลองนึกถึงอาร์เรย์ แฮช สตริง ช่วง ฯลฯ) รวมถึง “ตัวแจงนับ” ซึ่งเป็นชุดคิททั่วไปใดๆ ของวิธีการที่สามารถเรียกใช้กับข้อมูลนี้ได้ (แต่ละอย่าง แผนที่ เลือก และอื่นๆ) แต่หลังจากเพิ่งได้รับความเข้าใจพื้นฐานเกี่ยวกับออบเจ็กต์ โมดูล และมรดก ฉันได้ค้นพบว่าตัวแจงนับมีอะไรมากกว่านั้นมาก อาจเห็นได้ตั้งแต่แรกเห็น

แต่ก่อนอื่นเรามาทำความเข้าใจประเด็นเล็กๆ น้อยๆ ที่ทำให้เกิดความสับสนเกี่ยวกับข้อกำหนดเหล่านี้กันก่อน หากคุณศึกษาเอกสารประกอบ Ruby คุณจะพบหน้า “นับได้” ที่แยกต่างหากและดูเหมือนซ้ำซ้อน ซึ่งมีวิธีการต่างๆ มากมายที่ใช้กันทั่วไปในคลาสคอลเลกชัน นี่เป็นโมดูลที่นับได้จริงๆ ซึ่งได้รับการออกแบบมาเพื่อมอบชุดมาตรฐานของการวนซ้ำและวิธีการเรียงลำดับให้กับคลาส Ruby ใดๆ ผ่านทางการรวม ดูเหมือนว่าโมดูลนี้จะจัดเตรียมวิธีการบางอย่างที่เห็นในคลาสคอลเลกชันหลัก เช่น Each_with_index ที่ขาดไม่ได้ ซึ่งเป็นวิธีที่ฉันจะอ้างอิงกลับไปในภายหลัง

หากคุณดูตรงรายการคลาส/โมดูล คุณจะเห็นรายการที่น่าสนใจอีกรายการหนึ่ง: Enumerator แต่นั่นไม่ใช่เพียงคำที่รับทั้งหมดสำหรับวิธีการวนซ้ำทั้งหมดเหล่านั้นใช่ไหม เหตุใดจึงจัดเป็นชั้นเรียน?

เราจะไปถึงจุดนั้น ก่อนอื่น ให้ฉันอธิบายว่าฉันข้ามเส้นทางกับชาติที่แปลกประหลาดของผู้แจกแจงนี้ได้อย่างไร ในขณะที่ทำงานก่อนงาน Flatiron School ของฉัน ฉันประสบปัญหาการเขียนโค้ดโดยเฉพาะ ฉันจำเนื้อหาที่แน่ชัดของปัญหาไม่ได้ ดังนั้นฉันจะสร้างเนื้อหาที่คล้ายกันขึ้นใหม่ที่นี่

Given an array of frowns, turn them upside down! Except for the third one.
[' :( ', ' :( ', ' :( ', ' :( ', ' :( ']

ยอดเยี่ยม! ฉันเรียนจาวาสคริปต์พื้นฐาน ฉันรู้วิธีการทำเช่นนี้

และ Ruby ก็มี map method เหมือนกัน ควรจะง่าย ตอนนี้ให้ฉันไปตรวจสอบเอกสารเพื่อให้แน่ใจว่าฉันได้รับไวยากรณ์ถูกต้อง — -

อะไรนะ- !? คุณจะสร้างวิธีอาเรย์ที่ไม่รู้เกี่ยวกับดัชนีได้อย่างไร ลองคิดดูสิ แต่ละอันมีข้อบกพร่องเหมือนกัน และต้องการให้คุณเรียก Each_with_index เพื่อรับดัชนี แต่ดูเหมือนจะไม่มีวิธี map_with_index ทำไมรูบี้ถึงเป็นแบบนี้? แล้วสิ่งนี้ก็ดึงดูดสายตาของฉัน:

“แผนที่.with_index?” วิธีการ .with_index ทำหน้าที่อะไร ประสบการณ์และสัญชาตญาณของฉันบอกฉันว่าแผนที่ควรส่งคืนอะไรก็ตามที่ส่งคืนเมื่อไม่มีการบล็อก ซึ่งจากนั้นจะถูกดำเนินการโดยวิธี "with_index" นี้ ฉันเคยใช้ฟังก์ชันนี้บ่อยครั้งเมื่อเชื่อมโยงวิธีการรวบรวมอื่นๆ เข้าด้วยกัน เช่น แยก เข้าร่วม เรียงลำดับ ย้อนกลับ หรือ uniq เหตุใดจึงใช้งานได้ดังที่แสดงไว้ที่นี่ อ่านเพิ่มเติมแสดงให้เห็นว่าสิ่งนี้จะใช้ได้ผลเช่นกัน:

ขอย้ำอีกครั้งว่า ความเข้าใจของฉันคือแต่ละวิธีส่งคืนคอลเลกชันดั้งเดิมโดยไม่มีการแก้ไข ดังนั้น Each_with_index นี้ไม่ควรทำอะไรเลย จากนั้นจึงส่งต่ออาร์เรย์ไปยังแผนที่ map รู้เกี่ยวกับดัชนีได้อย่างไร

ฉันเห็นได้อย่างชัดเจนว่าตัวอย่างเหล่านี้ทำงานสำเร็จ แต่ฉันไม่รู้จะอธิบายว่าทำไม แต่ด้วยความที่ค่อนข้างใหม่กับ Ruby และยังมีงานอีกมากที่ต้องทำให้สำเร็จ ฉันจึงมองว่ามันเป็นกลอุบายทางวากยสัมพันธ์แปลก ๆ ที่ฉันอาจจะเข้าใจในภายหลังและเดินหน้าต่อไป

— กรอไปข้างหน้าหลายสัปดาห์ —

ตอนนี้ฉันเข้าสู่สัปดาห์แรกที่ Flatiron School แล้ว เรากำลังเรียนรู้พื้นฐานของการเขียนโปรแกรมเชิงวัตถุอย่างรวดเร็ว รวมถึงคลาส อินสแตนซ์ และอื่นๆ เมื่อถึงจุดหนึ่งในห้องปฏิบัติการ ความผิดปกติของตัววนซ้ำแบบลูกโซ่แบบเก่านั้นก็ปรากฏขึ้นอีกครั้ง มันยังคงเป็นปริศนาสำหรับฉัน แต่ตอนนี้ฉันคุ้นเคยและคุ้นเคยกับ Ruby มากขึ้นแล้ว ฉันจึงกลับไปดูเอกสารเพื่อดูอีกครั้ง นั่นคือตอนที่ฉันสังเกตเห็นสิ่งนี้:

ใช่ นี่เป็นครั้งแรกที่ฉันสังเกตเห็นข้อความตัวหนาขนาดใหญ่ใต้ข้อความตัวหนาขนาดใหญ่อื่น ๆ ที่ฉันอ้างถึงก่อนหน้านี้โดยตรง ในการป้องกันของฉัน มันเหมือนกับว่านี่เป็นครั้งแรกที่ฉันเข้าใจมันมากกว่า ดูในตัวอย่างก่อนหน้านี้ของฉัน โดยที่ฉันสันนิษฐานว่า map และ Each_with_index ถูกเรียกโดยไม่มีบล็อก ฉันพูดถูก อย่างไรก็ตาม สิ่งที่ฉันไม่ทราบก็คือ จริงๆ แล้วพวกเขาไม่ได้ส่งคืนอาร์เรย์และส่งต่อไปยังวิธีการต่อไปนี้ แต่กลับส่งคืนตัวแจงนับเหล่านี้แทน อัศจรรย์! เดี๋ยวก่อนแล้วตัวแจงนับคืออะไรอีกครั้ง?

ขั้นตอนต่อไปคือไปที่ "หน้าเอกสารตัวแจงนับ" ซึ่งเราจะอ่านได้ว่านี่คือ "คลาสที่อนุญาตการวนซ้ำทั้งภายในและภายนอก" แต่แทนที่จะท่องเอกสาร เรามาดู IRB กันดีกว่าว่าหน้าตาเป็นอย่างไร ฉันอยากจะสัมผัสมัน

ก่อนอื่น เรารู้ว่าวิธีหนึ่งที่เราจะได้รับตัวแจงนับคือการเรียกเมธอดตัววนซ้ำบางตัวโดยไม่มีการบล็อก

นั่นมัน! ดูคุ้นๆ นะ มันเป็นตัวอย่างของคลาส Enumerator แต่มันทำอะไรได้บ้าง? คุณมีวิธีการอะไรบ้าง?

ทันทีที่มีวิธี with_index อันลึกลับของเราจากเมื่อก่อน และแผนที่เพื่อนเก่าของเราและการเลือกก็อยู่ที่นี่เช่นกัน พร้อมด้วยวิธีการอื่น ๆ ที่คุ้นเคยมากมาย มันเริ่มชัดเจนแล้ว เมื่อเรารันเมธอดที่ถูกลูกโซ่เหล่านี้ เราไม่ได้เรียกเมธอดอาร์เรย์ แต่เรากำลังเรียกเมธอดอินสแตนซ์ตัวแจงนับพิเศษเหล่านี้ นี่จะอธิบายว่าทำไม map จึงสามารถให้ดัชนีเหล่านั้นเป็นบล็อกได้ ซึ่งแตกต่างจากวิธีการ map อาร์เรย์ปกติ

และเราจะเห็นได้ที่นี่ว่าตัวแจงนับรักษาตรรกะการส่งคืนของมันไว้ เช่น เมื่อเราเรียกแต่ละตัวบนมันและกำหนดบล็อก มันจะจำได้ว่ามันถูกสร้างขึ้นโดยวิธีการแมป และส่งกลับผลลัพธ์ของผลผลิตแผนที่

นอกจากนี้ ด้วยการเล่นกับวิธีการแจกแจงบางวิธี เราจะเห็นความสามารถที่น่าสนใจอื่นๆ:

ผู้แจงนับยังตระหนักถึงการวนซ้ำของตัวเอง “next” ส่งกลับค่าและเลื่อนการวนซ้ำ พยายามต่อไปจนสุดทางแล้วคุณจะได้รับข้อผิดพลาด การย้อนกลับจะดึงการวนซ้ำกลับไปยังจุดเริ่มต้น ในขณะที่ peek จะส่งกลับค่าที่จุดปัจจุบันของการวนซ้ำ แต่จะไม่คืบหน้า

มีวิธีการเฉพาะตัวแจงนับที่น่าสนใจอื่นๆ อีกจำนวนหนึ่ง เช่นเดียวกับการโต้ตอบการเชื่อมโยงห่วงโซ่การแจงนับที่แปลกและน่าประหลาดใจ ดูเหมือนว่าจะมีความเป็นไปได้มากมายในการสร้างตัวอย่างตัวแจงนับของคุณเองด้วยตรรกะภายในที่เป็นเอกลักษณ์ของตัวเอง แต่หัวข้อเหล่านั้นอยู่นอกเหนือขอบเขตของโพสต์นี้เล็กน้อย ซึ่งเป้าหมายหลักของฉันคือการแนะนำคลาส Enumerator และพยายามอธิบายตรรกะที่ไม่ได้ใช้งานง่ายของห่วงโซ่เมธอดตัววนซ้ำเหล่านี้ และหวังว่าหากใครก็ตามที่อ่านข้อความนี้บังเอิญไปเจอเหตุการณ์การแจงนับ คุณคงเตรียมตัวได้ดีขึ้นเล็กน้อย