เหตุผลของคำสั่ง return ในการเรียกใช้ฟังก์ชันแบบเรียกซ้ำ


14

ฉันเพิ่งสงสัยในใจ รูทีนย่อยต่อไปนี้ (เพื่อค้นหาองค์ประกอบในรายการ) มีคำสั่ง return ที่ท้าย:

list *search_list(list *l, item_type x) {
  if (l == NULL) return(NULL);
  if (l->item == x)
    return(l);
  else
    return( search_list(l->next, x) );
}

ฉันไม่สามารถรับความสำคัญของคำสั่ง return ในตอนท้าย (เช่น return search_list (l-> next, x)) มันจะมีประโยชน์จริง ๆ ถ้าใครสามารถอธิบายแนวคิดนี้โดยใช้โมเดลสแต็ก


หากในระยะแรกของรายการที่ไม่ได้เป็นผลการค้นหาผ่านส่วนที่เหลือของรายการ นี่คือสิ่งที่คนสุดท้ายreturnทำ
จอร์โจ

@ Giorgio ทำไมไม่เพียง แต่การเรียกใช้ฟังก์ชั่นเพียงพอแล้วทำไมต้องกลับมาก่อน?
user1369975

7
เนื่องจากคุณต้องการส่งคืนค่าที่ฟังก์ชันส่งคืน
Esailija

7
Downvoters: โปรดตระหนักว่าขึ้นอยู่กับพื้นหลังของสหกรณ์ก็ไม่ได้ทั้งหมดที่เห็นได้ชัดว่าสิ่งที่returnทำ อันที่จริงแล้วในภาษาที่ใช้งานได้ (และภาษาผสมบางอย่างเช่น Scala) return ไม่จำเป็น : ค่าของฟังก์ชันแบบเรียกซ้ำคือค่าของการแสดงออกครั้งสุดท้าย เพียงแค่เขียนsearch_list(l->next, x)โดยไม่returnต้องทำงานใน Scala! ความหมายของreturnคำสั่งนั้นชัดเจนสำหรับโปรแกรมเมอร์ที่มีพื้นฐานที่จำเป็นเท่านั้น
Andres F.

OP: ข้อมูลโค้ดของคุณเขียนเป็น C หรือไม่
Andres F.

คำตอบ:


19

ข้อความสั่ง return ส่งค่ากลับไปยังผู้เรียกทันทีของ call-frame ของฟังก์ชันปัจจุบัน ในกรณีของการเรียกซ้ำผู้ที่โทรเข้ามาในทันทีสามารถเป็นการเรียกใช้ฟังก์ชันเดียวกันอีกครั้งได้

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

สมมติว่าค่าส่งคืนที่ไม่ได้ใช้จะถูกทิ้งอย่างเงียบ ๆ หากคุณเขียนโค้ดดังนี้:

list *search_list(list *l, item_type x) {
  if (l == NULL) return(NULL);
  if (l->item == x)
    return(l);
  else
    search_list(l->next, x); // no return!
}

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

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


FWIW, Perl คืนค่าผลลัพธ์ของนิพจน์สุดท้ายโดยอัตโนมัติซึ่งฉันคิดว่ามันจะใช้ค่าที่ส่งคืน แต่ฉันไม่ได้สัมผัสเป็นเวลาหลายปีดังนั้นฉันจึงไม่แน่ใจ
Bobson

1

สองสิ่ง; การส่งคืนรายการทั้งหมดในกรณีที่คุณพบ "x" ที่คุณต้องการไม่จำเป็นต้องรับประกันการใช้การเรียกซ้ำ แต่คุณควรพิจารณาสิ่งต่อไปนี้:

สมมติว่าคุณกำลังค้นหาค่า X = "ธันวาคม" และรายการของคุณคือค่าตัวเลขของเดือนของปีตัวชี้ไปยังเดือนถัดไปและรายการ l-> ในรายการนั้นเป็นชื่อที่สะกดออกมาของ เดือน (มกราคม, กุมภาพันธ์, ... , ธันวาคม) คุณต้องการผลตอบแทนสามอย่างสำหรับผลลัพธ์ที่เป็นไปได้ อันแรกคืน (NULL) เป็นสิ่งจำเป็นหากรายการไม่มี X ที่คุณต้องการ ประการที่สอง (return (l)) คืนค่ารายการในกรณีนี้ให้คุณรู้ว่าคุณพบ "x" สุดท้ายคือรูปแบบสแต็คที่เข้ามาเล่น การเรียกใช้ฟังก์ชันต่อเนื่องจะมีการปรับปรุงตัวแปรท้องถิ่น (โดยเฉพาะ l-> รายการ) ดังนี้:

1: l->item = January
   returns search_list(l->next, x)
2: l->item = February
   returns search_list(l->next, x)
3-11: March, April, May, June, July, August, September, October, November
   all return search_list(l->next, x)
12: l->item = December
  This matches the second if() and returns your list, letting you know you found your search item.

ขอบคุณสำหรับภาพประกอบของคุณ แต่อย่าใช้ประโยชน์จากผลตอบแทนล่าสุด
จริงๆ

คุณจะไม่ได้รับขั้นตอนที่ผ่านมา 1
panhandel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.