อธิบายการประเมินแบบขี้เกียจ
คำนวณค่าเมื่อจำเป็นเท่านั้น
อธิบายการประเมินแบบขี้เกียจ เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน
ความขี้เกียจคืออะไร
ใน Scala ค่าส่วนใหญ่เป็นแบบ เข้มงวด กล่าวคือจะถูกคำนวณทันทีที่กำหนดค่า ความขี้เกียจจะเปลี่ยนพฤติกรรมนี้ ค่าที่ขี้เกียจจะถูกคำนวณเมื่อจำเป็นต้องใช้เป็นครั้งแรกเท่านั้น และจะไม่คำนวณก่อนหน้านั้น
สิ่งนี้สำคัญเมื่อการคำนวณมีค่าใช้จ่ายสูง อาจล้มเหลว หรืออาจไม่ถูกใช้งานเลย เหตุใดจึงต้องเสียทรัพยากรกับงานที่ไม่มีใครร้องขอ
val แบบเข้มงวด
val ปกติจะประเมินค่าด้านขวาทันที แม้ว่าคุณจะไม่อ่านค่านั้นอีกเลย
เรียกใช้โค้ดนี้แล้วสังเกตว่า "กำลังคำนวณ" ถูกพิมพ์ก่อน "หลังจากนั้น" งานเกิดขึ้นในเวลาที่กำหนดค่า
object Demo extends App {
val x = { println("computing"); 42 }
println("after")
println(x)
}lazy val
เติม val ด้วย lazy แล้วการประเมินค่าจะเลื่อนไปจนกว่าจะมีการเข้าถึงครั้งแรก
ในที่นี้ "หลังจากนั้น" จะถูกพิมพ์ก่อน จากนั้น "กำลังคำนวณ" จะถูกพิมพ์เมื่ออ่านค่า x เท่านั้น ผลลัพธ์ยังถูกแคชไว้ด้วย ดังนั้นส่วนเนื้อหาจะทำงานไม่เกินหนึ่งครั้ง
object Demo extends App {
lazy val x = { println("computing"); 42 }
println("after")
println(x)
println(x)
}พารามิเตอร์แบบ by-name
พารามิเตอร์ที่ประกาศเป็น => A จะถูกส่งผ่านแบบ by name กล่าวคืออาร์กิวเมนต์จะไม่ถูกประเมินจนกว่าจะถูกใช้ภายในเมธอด
นี่คือพื้นฐานของความขี้เกียจ LazyList ใช้พารามิเตอร์แบบ by-name เพื่อไม่คำนวณส่วนท้ายจนกว่าจะมีการร้องขอ
def maybe(cond: Boolean, value: => Int): Int =
if (cond) value else 0
val r = maybe(false, { println("side"); 99 })
// "side" never prints; value was unusedทำความรู้จักกับ LazyList
LazyList คือลำดับแบบขี้เกียจของ Scala ซึ่งมาแทนที่ Stream รุ่นเก่าใน 2.13 ขึ้นไป ส่วนหัวจะถูกประเมินค่าอย่างกระตือรือร้น แต่ส่วนท้ายจะเป็นแบบขี้เกียจ
สมาชิกจะถูกสร้างตามคำขอและจดจำค่าไว้เมื่อคำนวณแล้ว ดังนั้นเซลล์เดิมจะไม่ถูกคำนวณซ้ำ
val ll = LazyList(1, 2, 3)
println(ll)
// prints LazyList(<not computed>) until forcedการบังคับให้ประเมินค่า
LazyList จะยังไม่ถูกประเมินค่าจนกว่าคุณจะบังคับให้ประเมิน การเรียกใช้ toList, foreach หรือการพิมพ์สมาชิกแต่ละตัวจะบังคับให้เซลล์เหล่านั้นถูกประเมิน
REPL จะแสดง <not computed> สำหรับส่วนท้ายที่ยังไม่ถูกคำนวณ การบังคับให้ประเมินจะแสดงค่าจริง
object Demo extends App {
val ll = LazyList(1, 2, 3)
println(ll.toList)
}ตัวดำเนินการ #::
คุณเพิ่มสมาชิกไว้ด้านหน้าของ LazyList ได้ด้วย #:: ต่างจาก :: ของลิสต์ ตัวถูกดำเนินการด้านขวาของ #:: จะเป็นแบบ by-name ดังนั้นส่วนท้ายจะยังไม่ถูกสร้างจนกว่าจะจำเป็น
ทำให้คุณอธิบายลำดับที่ส่วนที่เหลือถูกคำนวณแบบขี้เกียจได้
val ll = 1 #:: 2 #:: 3 #:: LazyList.empty
println(ll.head)การจดจำผลลัพธ์
เมื่อคำนวณเซลล์ของ LazyList แล้ว ค่าจะถูกจัดเก็บไว้ การอ่านซ้ำจึงไม่เสียค่าใช้จ่าย และนิพจน์ที่สร้างค่าจะไม่ทำงานซ้ำ
เรียกใช้โค้ดนี้: "คำนวณ" จะถูกพิมพ์เฉพาะเมื่อเข้าถึงสมาชิกแต่ละตัวที่ถูกบังคับให้ประเมินเป็นครั้งแรก ไม่ใช่เมื่ออ่านซ้ำ
object Demo extends App {
val ll = LazyList(1, 2).map { n =>
println("calc " + n); n * 10
}
println(ll.head)
println(ll.head)
}ส่วนท้ายแบบขี้เกียจในการทำงาน
เนื่องจากส่วนท้ายเป็นแบบขี้เกียจ คุณจึง map บน LazyList ได้ และจะมีการคำนวณเฉพาะสมาชิกที่คุณเข้าถึง
ในที่นี้ "map" จะถูกพิมพ์เพียงครั้งเดียว แม้ว่าลิสต์จะมีสามสมาชิก เพราะมีเพียงส่วนหัวที่ถูกบังคับให้ประเมิน
object Demo extends App {
val r = LazyList(1, 2, 3).map { n =>
println("map " + n); n + 1
}
println(r.head)
}เหตุผลที่ความขี้เกียจมีประโยชน์
ความขี้เกียจช่วยให้ทำสามสิ่งได้ ได้แก่ หลีกเลี่ยงงานที่ไม่ได้ใช้ สร้างลำดับอนันต์ และแยกวิธีอธิบายการคำนวณออกจากปริมาณงานที่ทำจริง
คุณเขียน pipeline ทั้งหมดเพียงครั้งเดียว ส่วนผู้ใช้จะตัดสินใจว่าจะดึงสมาชิกออกมากี่ตัว
ข้อควรระวัง
ความขี้เกียจมีต้นทุน LazyList จะจดจำค่า ดังนั้นการเก็บการอ้างอิงถึงส่วนหัวจะทำให้สมาชิกทุกตัวที่ถูกบังคับให้ประเมินยังคงอยู่ในหน่วยความจำ สำหรับข้อมูลขนาดใหญ่หรือข้อมูลอนันต์ หลีกเลี่ยงการเก็บส่วนหัวไว้
นอกจากนี้ ผลข้างเคียงในโค้ดแบบขี้เกียจอาจทำงานในเวลาที่คาดไม่ถึง ซึ่งทำให้การแก้ไขข้อผิดพลาดสับสนได้
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจเกี่ยวกับการประเมินค่าแบบขี้เกียจ
สรุปทบทวน
การประเมินค่าแบบเข้มงวดจะทำงานทันที ส่วนการประเมินค่าแบบขี้เกียจจะเลื่อนไปจนกว่าจะจำเป็น lazy val และพารามิเตอร์แบบ by-name (=> A) คือกลไกพื้นฐาน
LazyList สร้างต่อยอดจากกลไกเหล่านี้ โดยมีส่วนหัวแบบกระตือรือร้น ส่วนท้ายแบบขี้เกียจที่จดจำค่า และถูกบังคับให้ประเมินผ่าน toList หรือการเข้าถึงสมาชิก ถัดไปเราจะสร้าง LazyLists ด้วยตนเอง
คำถามที่พบบ่อย
บทเรียน “อธิบายการประเมินแบบขี้เกียจ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “อธิบายการประเมินแบบขี้เกียจ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “อธิบายการประเมินแบบขี้เกียจ”
คำนวณค่าเมื่อจำเป็นเท่านั้น คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “อธิบายการประเมินแบบขี้เกียจ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม
ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- อธิบายการประเมินแบบขี้เกียจ
- สร้าง LazyList
- สตรีมไม่สิ้นสุด
- การดึงและกรองแบบขี้เกียจ