0Pricing
Scala for Backend Engineering & Functional Programming · บทเรียน

อธิบายการประเมินแบบขี้เกียจ

คำนวณค่าเมื่อจำเป็นเท่านั้น

อธิบายการประเมินแบบขี้เกียจ เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. อธิบายการประเมินแบบขี้เกียจ
  2. สร้าง LazyList
  3. สตรีมไม่สิ้นสุด
  4. การดึงและกรองแบบขี้เกียจ
← กลับไปที่ Scala for Backend Engineering & Functional Programming