ฟังก์ชัน tailrec
เพิ่มประสิทธิภาพการเรียกซ้ำ
ฟังก์ชัน tailrec เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
การเรียกซ้ำแบบหางคืออะไร
ฟังก์ชันเป็นแบบเรียกซ้ำแบบหางเมื่อการเรียกซ้ำเป็นการดำเนินการสุดท้ายอย่างแท้จริง จากนั้น Kotlin สามารถปรับให้เป็นลูปเพื่อหลีกเลี่ยงสแตกโอเวอร์โฟลว์ได้
tailrec fun countdown(n: Int) {
if (n < 0) return
println(n)
countdown(n - 1)
}
fun main() {
countdown(3)
}ตัวแก้ไขการเรียกซ้ำแบบหาง
เพิ่มตัวแก้ไข tailrec แล้วคอมไพเลอร์จะเขียนการเรียกซ้ำใหม่ให้เป็นการวนซ้ำ โดยใช้พื้นที่สแตกคงที่
tailrec fun sum(n: Int, acc: Int = 0): Int {
if (n == 0) return acc
return sum(n - 1, acc + n)
}
fun main() {
println(sum(100))
}รูปแบบ Accumulator
หากต้องการทำให้การเรียกซ้ำอยู่ในรูปแบบหาง ให้ส่งผลลัพธ์ต่อผ่านพารามิเตอร์ตัวสะสม เพื่อไม่ให้เหลือสิ่งใดต้องคำนวณหลังการเรียกใช้
tailrec fun factorial(n: Int, acc: Long = 1): Long {
if (n <= 1) return acc
return factorial(n - 1, acc * n)
}
fun main() {
println(factorial(10))
}เหตุผลที่การเรียกต้องเป็นการดำเนินการสุดท้าย
หากมีสิ่งใดเกิดขึ้นหลังการเรียกซ้ำ เช่น การคูณผลลัพธ์ของการเรียกนั้น การเรียกจะไม่อยู่ในตำแหน่งหางและไม่สามารถปรับให้เหมาะสมได้
tailrec fun length(s: String, acc: Int = 0): Int {
if (s.isEmpty()) return acc
return length(s.drop(1), acc + 1)
}
fun main() {
println(length("hello"))
}ตัวอย่างโต้แย้งการเรียกซ้ำที่ไม่ใช่แบบหาง
ฟังก์ชันแฟกทอเรียลนี้ไม่ใช่การเรียกซ้ำแบบหาง เนื่องจากการคูณเกิดขึ้นหลังจากการเรียกส่งคืนค่า หากระบุ tailrec คอมไพเลอร์จะแสดงคำเตือน
fun badFactorial(n: Int): Long {
if (n <= 1) return 1
return n * badFactorial(n - 1)
}
fun main() {
println(badFactorial(5))
}การหลีกเลี่ยงสแตกโอเวอร์โฟลว์
การเรียกซ้ำลึกโดยไม่มี tailrec อาจทำให้โปรแกรมล้มเหลวได้ แต่เมื่อใช้ tailrec แม้อินพุตจะมีขนาดใหญ่ก็ยังทำงานด้วยพื้นที่สแตกคงที่
tailrec fun count(n: Int, acc: Int = 0): Int {
if (n == 0) return acc
return count(n - 1, acc + 1)
}
fun main() {
println(count(100000))
}การตรวจสอบโดยคอมไพเลอร์
หากคุณระบุ tailrec ให้ฟังก์ชัน แต่การเรียกไม่ได้อยู่ในตำแหน่งหาง คอมไพเลอร์จะแสดงคำเตือนและจะไม่ปรับโค้ดให้เหมาะสม โปรดเชื่อคำเตือนนั้น
tailrec fun gcd(a: Int, b: Int): Int {
if (b == 0) return a
return gcd(b, a % b)
}
fun main() {
println(gcd(48, 18))
}การเรียกซ้ำแบบหางกับลูป
ฟังก์ชัน tailrec จะถูกคอมไพล์เป็นโค้ดที่ใกล้เคียงกับลูปที่เทียบเท่ากัน แต่ยังคงสื่ออัลกอริทึมในรูปแบบการเรียกซ้ำ
tailrec fun powerOfTwo(n: Int, acc: Long = 1): Long {
if (n == 0) return acc
return powerOfTwo(n - 1, acc * 2)
}
fun main() {
println(powerOfTwo(10))
}พารามิเตอร์หลายตัว
ฟังก์ชันเรียกซ้ำแบบหางมักส่งผ่านพารามิเตอร์สถานะหลายตัว โดยทุกตัวจะได้รับการอัปเดตในการเรียกซ้ำ
tailrec fun fib(n: Int, a: Long = 0, b: Long = 1): Long {
if (n == 0) return a
return fib(n - 1, b, a + b)
}
fun main() {
println(fib(20))
}การกลับลำดับด้วย tailrec
ตัวสะสมสามารถค่อย ๆ สร้างผลลัพธ์ เช่น สตริงที่กลับลำดับแล้ว
tailrec fun reverse(s: String, acc: String = ""): String {
if (s.isEmpty()) return acc
return reverse(s.drop(1), s.first() + acc)
}
fun main() {
println(reverse("kotlin"))
}การค้นหาที่ใช้งานได้จริง
การค้นหาแบบวนซ้ำสามารถแปลงเป็นการเรียกซ้ำแบบหางได้อย่างตรงไปตรงมา
tailrec fun indexOf(list: List<Int>, target: Int, i: Int = 0): Int {
if (i >= list.size) return -1
if (list[i] == target) return i
return indexOf(list, target, i + 1)
}
fun main() {
println(indexOf(listOf(5, 6, 7), 7))
}ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจเกี่ยวกับฟังก์ชัน tailrec
สรุปทบทวน
คุณได้เรียนรู้เรื่องฟังก์ชันเรียกซ้ำแบบหาง:
tailrecเปลี่ยนการเรียกซ้ำในตำแหน่งหางให้เป็นลูป เพื่อหลีกเลี่ยงสแตกโอเวอร์โฟลว์- การเรียกซ้ำต้องเป็นการดำเนินการสุดท้าย
- ใช้พารามิเตอร์ตัวสะสมเพื่อให้ได้รูปแบบหาง
- คอมไพเลอร์จะแสดงคำเตือนเมื่อไม่สามารถปรับฟังก์ชันให้เหมาะสมได้
tailrec fun sum(n: Int, acc: Int = 0): Int =
if (n == 0) acc else sum(n - 1, acc + n)
fun main() {
println(sum(50))
}คำถามที่พบบ่อย
บทเรียน “ฟังก์ชัน tailrec” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ฟังก์ชัน tailrec” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ฟังก์ชัน tailrec”
เพิ่มประสิทธิภาพการเรียกซ้ำ คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “ฟังก์ชัน tailrec” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม
ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ฟังก์ชัน Infix
- การสร้าง API ลักษณะ DSL
- ฟังก์ชัน tailrec
- ควรใช้แต่ละแบบเมื่อใด