ฉันสงสัยว่าขณะที่ลูปนั้นวนซ้ำอยู่ภายในหรือไม่
ฉันคิดว่ามันเป็นเพราะในขณะที่วงสามารถมองเห็นเป็นฟังก์ชั่นที่เรียกตัวเองว่าในตอนท้าย ถ้ามันไม่ใช่การเรียกซ้ำแล้วความแตกต่างคืออะไร?
ฉันสงสัยว่าขณะที่ลูปนั้นวนซ้ำอยู่ภายในหรือไม่
ฉันคิดว่ามันเป็นเพราะในขณะที่วงสามารถมองเห็นเป็นฟังก์ชั่นที่เรียกตัวเองว่าในตอนท้าย ถ้ามันไม่ใช่การเรียกซ้ำแล้วความแตกต่างคืออะไร?
คำตอบ:
ลูปเป็นอย่างมากไม่เรียกซ้ำ ในความเป็นจริงพวกเขาเป็นตัวอย่างที่สำคัญของฝั่งตรงข้ามกลไก: ซ้ำ
ประเด็นของการเรียกซ้ำคือองค์ประกอบหนึ่งของการประมวลผลเรียกอินสแตนซ์อื่นของตัวเอง เครื่องจักรควบคุมลูปเพียงกระโดดกลับไปที่จุดเริ่มต้นเท่านั้น
การกระโดดไปรอบ ๆ ในรหัสและการเรียกบล็อกรหัสอื่นเป็นการดำเนินการที่แตกต่างกัน ตัวอย่างเช่นเมื่อคุณข้ามไปยังจุดเริ่มต้นของลูปตัวแปรควบคุมการวนซ้ำยังคงมีค่าเหมือนเดิมก่อนการกระโดด แต่ถ้าคุณเรียกใช้อินสแตนซ์อื่นของรูทีนที่คุณอยู่อินสแตนซ์ใหม่จะมีสำเนาใหม่ทั้งหมดที่ไม่เกี่ยวข้องกับตัวแปรทั้งหมด อย่างมีประสิทธิภาพตัวแปรหนึ่งสามารถมีหนึ่งค่าในระดับแรกของการประมวลผลและค่าอื่นในระดับที่ต่ำกว่า
ความสามารถนี้มีความสำคัญอย่างยิ่งสำหรับอัลกอริธึมการวนซ้ำในการทำงานและนี่คือเหตุผลที่คุณไม่สามารถจำลองการเรียกซ้ำผ่านการวนซ้ำโดยไม่จัดการเฟรมที่เรียกว่าซึ่งติดตามค่าเหล่านั้นทั้งหมด
การพูดว่า X นั้นเป็นเนื้อแท้ใน Y จะสมเหตุสมผลถ้าคุณมีระบบ (เป็นทางการ) อยู่ในใจว่าคุณกำลังแสดง X เข้ามาหากคุณนิยามความหมายของwhile
คำว่าแลคด้าแคลคูลัสคุณอาจพูดถึงการเรียกซ้ำ *; หากคุณกำหนดไว้ในแง่ของเครื่องลงทะเบียนคุณอาจจะไม่
ในกรณีใดกรณีหนึ่งผู้คนอาจไม่เข้าใจคุณถ้าคุณเรียกใช้ฟังก์ชันแบบเรียกซ้ำเนื่องจากมันมีการวนรอบสักครู่
* fold
แม้ว่าบางทีอาจจะเป็นเพียงทางอ้อมเช่นถ้าคุณกำหนดมันในแง่ของ
while
เรียกซ้ำแบบสร้างโดยทั่วไปแล้วเป็นคุณสมบัติของฟังก์ชั่นฉันก็ไม่สามารถคิดอย่างอื่นที่จะอธิบายว่า "ซ้ำ" ในบริบทนี้
ขึ้นอยู่กับมุมมองของคุณ
ถ้าคุณดูที่ทฤษฎีการคำนวณแล้วซ้ำและการเรียกซ้ำมีการแสดงออกอย่างเท่าเทียมกัน สิ่งนี้หมายความว่าคุณสามารถเขียนฟังก์ชันที่คำนวณบางอย่างและไม่สำคัญว่าคุณจะทำซ้ำหรือวนซ้ำคุณจะสามารถเลือกวิธีการทั้งสองได้ ไม่มีสิ่งใดที่คุณสามารถคำนวณซ้ำได้ซึ่งคุณไม่สามารถคำนวณซ้ำและในทางกลับกันได้ (แม้ว่าการทำงานภายในของโปรแกรมอาจแตกต่างกัน)
ภาษาการเขียนโปรแกรมส่วนใหญ่ไม่ถือว่าการเรียกซ้ำและการวนซ้ำเหมือนกันและด้วยเหตุผลที่ดี โดยทั่วไปการเรียกซ้ำหมายถึงภาษา / คอมไพเลอร์จัดการกับ call stack และการทำซ้ำหมายความว่าคุณอาจต้องจัดการกับ stack ด้วยตนเอง
แต่มีภาษา- ภาษาการทำงานโดยเฉพาะอย่างยิ่ง -ซึ่งในสิ่งที่ชอบลูป (สำหรับขณะ) เป็นแน่นอนน้ำตาลประโยคเพียง แต่สำหรับการเรียกซ้ำและดำเนินการอยู่เบื้องหลังว่าวิธีการ สิ่งนี้มักจะเป็นที่ต้องการในภาษาที่ใช้งานได้เพราะพวกเขามักจะไม่มีแนวคิดของการวนซ้ำเป็นอย่างอื่นและการเพิ่มมันจะทำให้แคลคูลัสมีความซับซ้อนมากขึ้นด้วยเหตุผลเชิงปฏิบัติเพียงเล็กน้อย
ดังนั้นไม่มีพวกเขาไม่ได้เป็นพื้นฐานเดียวกัน พวกเขามีความหมายเท่า ๆ กันซึ่งหมายความว่าคุณไม่สามารถคำนวณสิ่งที่ซ้ำ ๆ กันคุณไม่สามารถคำนวณซ้ำและในทางกลับกัน แต่นั่นเป็นเรื่องเกี่ยวกับมันในกรณีทั่วไป
โปรดทราบว่าเรากำลังพูดถึงโปรแกรมเวียนเกิดที่นี่ มีการเรียกซ้ำในรูปแบบอื่น ๆ เช่นในโครงสร้างข้อมูล (เช่นต้นไม้)
หากคุณมองจากมุมมองการนำไปใช้การเรียกซ้ำและการวนซ้ำนั้นค่อนข้างไม่เหมือนกัน การเรียกซ้ำสร้างเฟรมสแต็กใหม่สำหรับการโทรทุกครั้ง ทุกขั้นตอนของการเรียกซ้ำเป็นแบบในตัวเองรับอาร์กิวเมนต์สำหรับการคำนวณจาก callee (ตัวเอง)
การวนซ้ำในทางกลับกันจะไม่สร้างเฟรมการโทร สำหรับพวกเขาบริบทจะไม่ได้รับการเก็บรักษาไว้ในแต่ละขั้นตอน สำหรับลูปโปรแกรมจะกระโดดกลับไปที่จุดเริ่มต้นของลูปจนกว่าเงื่อนไขลูปจะล้มเหลว
นี่เป็นเรื่องสำคัญที่ต้องรู้เนื่องจากมันสามารถสร้างความแตกต่างที่ต่างไปจากเดิมอย่างสิ้นเชิงในโลกแห่งความเป็นจริง สำหรับการเรียกซ้ำจะต้องบันทึกบริบททั้งหมดในทุกการโทร สำหรับการวนซ้ำคุณมีการควบคุมที่แม่นยำเกี่ยวกับตัวแปรที่อยู่ในหน่วยความจำและสิ่งที่ถูกบันทึกไว้
หากคุณมองอย่างนั้นคุณจะเห็นได้อย่างรวดเร็วว่าสำหรับภาษาส่วนใหญ่การทำซ้ำและการเรียกซ้ำจะแตกต่างกันโดยพื้นฐานและมีคุณสมบัติที่แตกต่างกัน ขึ้นอยู่กับสถานการณ์คุณสมบัติบางอย่างเป็นที่ต้องการมากกว่าและอื่น ๆ
recursion สามารถทำให้โปรแกรมง่ายขึ้นและง่ายต่อการทดสอบและพิสูจน์ การแปลงการวนซ้ำเป็นการวนซ้ำมักทำให้โค้ดซับซ้อนขึ้นเพิ่มโอกาสในการเกิดความล้มเหลว ในทางกลับกันการแปลงเป็นการวนซ้ำและการลดจำนวนการเรียกเฟรมสแต็กสามารถบันทึกหน่วยความจำที่จำเป็นได้
ความแตกต่างคือสแต็กโดยนัยและความหมาย
A ขณะที่ลูปที่ "เรียกตัวเองในตอนท้าย" ไม่มีสแต็กเพื่อรวบรวมข้อมูลเมื่อเสร็จแล้ว การทำซ้ำครั้งล่าสุดเป็นการตั้งค่าสถานะที่จะสิ้นสุดลง
การเรียกใช้ซ้ำไม่สามารถทำได้หากไม่มีสแต็กนี้โดยนัยซึ่งจะจดจำสถานะของงานที่ทำก่อนหน้านี้
มันเป็นความจริงที่คุณสามารถแก้ปัญหาการเรียกซ้ำด้วยการวนซ้ำถ้าคุณให้สิทธิ์การเข้าถึงสแต็กอย่างชัดเจน แต่การทำแบบนั้นไม่เหมือนกัน
ความแตกต่างทางความหมายเกี่ยวข้องกับความจริงที่ว่าการดูโค้ดแบบเรียกซ้ำเป็นการถ่ายทอดความคิดในรูปแบบที่แตกต่างจากรหัสวนซ้ำอย่างสิ้นเชิง รหัสซ้ำจะทำสิ่งต่าง ๆ ทีละขั้นตอน ยอมรับสถานะใด ๆ ก็ตามที่มาก่อนและทำงานเพื่อสร้างสถานะถัดไปเท่านั้น
รหัสที่เรียกซ้ำจะแบ่งปัญหาออกเป็นเศษส่วน ส่วนเล็ก ๆ นี้ดูเหมือนว่าส่วนใหญ่เพื่อให้เราสามารถทำเพียงส่วนนี้และส่วนเดียวกัน มันเป็นวิธีที่แตกต่างในการคิดถึงปัญหา มันทรงพลังมากและคุ้นเคย มากสามารถพูดได้ในไม่กี่บรรทัด คุณไม่สามารถออกจากวงในขณะที่แม้ว่าจะสามารถเข้าถึงสแต็ก
มันบานพับทั้งหมดเกี่ยวกับการใช้งานของคำว่าภายใน ในระดับภาษาการเขียนโปรแกรมพวกเขาจะมีความแตกต่างกันและความหมายทางไวยากรณ์และพวกเขามีประสิทธิภาพที่แตกต่างกันมากและใช้หน่วยความจำ แต่ถ้าคุณขุดลึกลงไปในทฤษฎีมากพอพวกเขาสามารถนิยามได้ในแง่ของกันและกันและดังนั้นจึง "เหมือนกัน" ในบางแง่มุมทางทฤษฎี
คำถามที่แท้จริงคือเมื่อไหร่ที่จะแยกแยะความแตกต่างระหว่างการวนซ้ำ (วนซ้ำ) และการเรียกซ้ำและเมื่อใดจึงเป็นประโยชน์เมื่อคิดว่ามันเป็นสิ่งเดียวกัน คำตอบคือเมื่อจริง ๆ แล้วการเขียนโปรแกรม (ตรงข้ามกับการเขียนหลักฐานทางคณิตศาสตร์) เป็นสิ่งสำคัญที่จะต้องแยกแยะระหว่างการวนซ้ำและการเรียกซ้ำ
การเรียกซ้ำสร้างเฟรมสแต็กใหม่เช่นชุดตัวแปรโลคัลใหม่สำหรับการโทรแต่ละครั้ง มีโอเวอร์เฮดและใช้พื้นที่บนสแต็กซึ่งหมายความว่าการเรียกซ้ำที่ลึกพออาจทำให้สแต็กมากเกินไปซึ่งทำให้โปรแกรมขัดข้อง การทำซ้ำในทางกลับกันเพียงแก้ไขตัวแปรที่มีอยู่ดังนั้นโดยทั่วไปจะเร็วกว่าและใช้หน่วยความจำในปริมาณคงที่เท่านั้น นี่คือความแตกต่างที่สำคัญมากสำหรับนักพัฒนา!
ในภาษาที่มี tail-call recursion (โดยทั่วไปคือภาษาที่ใช้งานได้) คอมไพเลอร์อาจสามารถเพิ่มประสิทธิภาพการโทรแบบเรียกซ้ำในลักษณะที่พวกเขาใช้หน่วยความจำจำนวนคงที่เท่านั้น ในภาษาเหล่านั้นความแตกต่างที่สำคัญไม่ใช่การวนซ้ำเทียบกับการเรียกซ้ำ แต่ไม่ใช่การเรียกซ้ำและเรียกซ้ำการเรียกซ้ำและเรียกซ้ำ
บรรทัดล่างสุด: คุณต้องสามารถบอกความแตกต่างได้ไม่เช่นนั้นโปรแกรมของคุณจะพัง
while
ลูปเป็นรูปแบบของการเรียกซ้ำดูตัวอย่างคำตอบที่ยอมรับสำหรับคำถามนี้ พวกเขาสอดคล้องกับμ-operator ในทฤษฎีการคำนวณ (ดูตัวอย่างที่นี่ )
รูปแบบทั้งหมดของfor
ลูปที่ย้ำในช่วงของตัวเลข, คอลเลกชัน จำกัด อาร์เรย์และอื่น ๆ ที่สอดคล้องกับการเรียกซ้ำดั้งเดิมเช่นดูที่นี่และที่นี่ โปรดทราบว่าfor
ลูปของ C, C ++, Java และอื่น ๆ เป็นน้ำตาลซินแทกติกสำหรับwhile
ลูปและดังนั้นจึงไม่สอดคล้องกับการเรียกซ้ำแบบดั้งเดิม Pascal for
loop เป็นตัวอย่างของการเรียกซ้ำแบบดั้งเดิม
ความแตกต่างที่สำคัญคือการเรียกซ้ำแบบดั้งเดิมจะสิ้นสุดลงเสมอในขณะที่การเรียกซ้ำแบบทั่วไป ( while
ลูป) อาจไม่สิ้นสุด
แก้ไข
คำอธิบายบางอย่างเกี่ยวกับความคิดเห็นและคำตอบอื่น ๆ "การเรียกซ้ำเกิดขึ้นเมื่อมีการกำหนดสิ่งต่าง ๆ ในแง่ของตัวเองหรือประเภทของมัน" (ดูวิกิพีเดีย ) ดังนั้น,
ขณะที่วนซ้ำภายในเรียกซ้ำ?
เนื่องจากคุณสามารถกำหนดwhile
วงในแง่ของตัวเอง
while p do c := if p then (c; while p do c))
แล้วใช่เป็นwhile
ห่วงเป็นรูปแบบของการเรียกซ้ำ ฟังก์ชั่นวนซ้ำเป็นอีกรูปแบบหนึ่งของการเรียกซ้ำ (อีกตัวอย่างหนึ่งของคำจำกัดความซ้ำ) รายการและต้นไม้เป็นรูปแบบอื่นของการเรียกซ้ำ
อีกคำถามหนึ่งที่สันนิษฐานโดยนัยโดยคำตอบและความคิดเห็นมากมายคือ
ในขณะที่ฟังก์ชั่นวนซ้ำและแบบเรียกซ้ำ?
คำตอบสำหรับคำถามนี้ไม่มี : เป็นwhile
ห่วงสอดคล้องกับฟังก์ชั่นหาง recursive ที่ตัวแปรที่มีการเข้าถึงโดยสอดคล้องห่วงข้อโต้แย้งของฟังก์ชันเวียนโดยปริยาย แต่เป็นคนอื่นได้ชี้ไม่ใช่หน้าที่หาง recursive ไม่สามารถสร้างแบบจำลองโดยwhile
ลูปโดยไม่ใช้สแต็กพิเศษ
ดังนั้นความจริงที่ว่า "a while
loop เป็นรูปแบบของการเรียกซ้ำ" ไม่ได้ขัดแย้งกับความจริงที่ว่า "บางฟังก์ชั่นที่เรียกซ้ำไม่สามารถแสดงออกได้ด้วยการwhile
วนซ้ำ"
FOR
ลูปสามารถคำนวณฟังก์ชัน recursive ดั้งเดิมทั้งหมดได้และภาษาที่มีเพียงWHILE
ลูปสามารถคำนวณฟังก์ชัน functions-recursive ทั้งหมดได้อย่างแน่นอน (และปรากฎว่าฟังก์ชัน rec-recursive นั้นเป็นฟังก์ชันที่ เครื่องทัวริงสามารถคำนวณได้) หรือเพื่อทำให้สั้น: การเรียกซ้ำแบบดั้งเดิมและ rec-recursion เป็นศัพท์ทางเทคนิคจากคณิตศาสตร์ / ทฤษฎีการคำนวณ
โทรหาง (หรือโทร recursive หาง) จะดำเนินการว่าเป็น "โกโตะมีข้อโต้แย้ง" (โดยไม่ผลักดันใด ๆเพิ่มเติมกรอบการโทรบนสแต็คโทร ) และในภาษาที่ทำงานบางคน (Ocaml สะดุดตา) เป็นวิธีปกติของการวนลูป
ดังนั้นในขณะที่ห่วง (ในภาษาที่มีพวกเขา) สามารถมองเห็นว่าลงท้ายด้วยหางเรียกร่างกายของมัน (หรือทดสอบหัวของมัน)
ในทำนองเดียวกันการโทรซ้ำแบบธรรมดา (ไม่ใช่การโทรหาง) สามารถจำลองโดยการวนซ้ำ (ใช้สแต็กบางตัว)
อ่านยังเกี่ยวกับการตและรูปแบบต่อเนื่องผ่าน
ดังนั้น "การเรียกซ้ำ" และ "การทำซ้ำ" จึงเทียบเท่ากันอย่างลึกซึ้ง
มันเป็นความจริงที่ว่าการเรียกซ้ำและไม่ จำกัด ในขณะที่ลูปจะเทียบเท่าในแง่ของการแสดงออกเชิงคอมพิวเตอร์ นั่นคือโปรแกรมใด ๆ ที่เขียนซ้ำสามารถเขียนใหม่ในโปรแกรมที่เทียบเท่าโดยใช้ลูปแทนและในทางกลับกัน ทั้งสองวิธีมีความสมบูรณ์แบบที่สามารถใช้ในการคำนวณฟังก์ชันใด ๆ ที่คำนวณได้
ความแตกต่างพื้นฐานในแง่ของการเขียนโปรแกรมคือการเรียกซ้ำทำให้คุณสามารถใช้ข้อมูลที่เก็บไว้ใน call stack ในการอธิบายเรื่องนี้สมมติว่าคุณต้องการพิมพ์องค์ประกอบของรายการที่เชื่อมโยงโดยลำพังโดยใช้การวนซ้ำหรือการเรียกซ้ำ ฉันจะใช้ C สำหรับรหัสตัวอย่าง:
typedef struct List List;
struct List
{
List* next;
int element;
};
void print_list_loop(List* l)
{
List* it = l;
while(it != NULL)
{
printf("Element: %d\n", it->element);
it = it->next;
}
}
void print_list_rec(List* l)
{
if(l == NULL) return;
printf("Element: %d\n", l->element);
print_list_rec(l->next);
}
ง่ายใช่มั้ย ทีนี้ลองทำการดัดแปลงนิดหน่อย: พิมพ์รายการในลำดับย้อนกลับ
สำหรับตัวแปรแบบเรียกซ้ำนี่คือการปรับเปลี่ยนเล็กน้อยสำหรับฟังก์ชั่นดั้งเดิม:
void print_list_reverse_rec(List* l)
{
if (l == NULL) return;
print_list_reverse_rec(l->next);
printf("Element: %d\n", l->element);
}
สำหรับฟังก์ชั่นการวนซ้ำเรามีปัญหา รายการของเรามีการเชื่อมโยงอย่างเดียวและสามารถข้ามไปข้างหน้าได้เท่านั้น แต่เนื่องจากเรากำลังพิมพ์แบบย้อนกลับเราจึงต้องเริ่มพิมพ์องค์ประกอบสุดท้าย เมื่อเราไปถึงองค์ประกอบสุดท้ายเราจะไม่สามารถกลับไปที่องค์ประกอบที่สองไปยังอีกต่อไปได้อีก
ดังนั้นเราจึงต้องทำการสำรวจใหม่ทั้งหมดหรือต้องสร้างโครงสร้างข้อมูลเสริมที่คอยติดตามองค์ประกอบที่เยี่ยมชมและจากนั้นเราก็สามารถพิมพ์ได้อย่างมีประสิทธิภาพ
ทำไมเราไม่มีปัญหานี้กับการเรียกซ้ำ เพราะในการเรียกซ้ำเรามีโครงสร้างข้อมูลเสริมอยู่แล้ว: การเรียกฟังก์ชันสแต็ก
เนื่องจากการเรียกซ้ำทำให้เราสามารถกลับไปที่การเรียกก่อนหน้าของการเรียกซ้ำด้วยตัวแปรท้องถิ่นและสถานะทั้งหมดสำหรับการโทรนั้นยังคงไม่เปลี่ยนแปลงเราได้รับความยืดหยุ่นบางอย่างที่น่าเบื่อในการจำลองในกรณีซ้ำ
ลูปเป็นรูปแบบพิเศษของการเรียกซ้ำเพื่อให้บรรลุภารกิจเฉพาะ (ซ้ำส่วนใหญ่) หนึ่งสามารถใช้วนซ้ำในลักษณะแบบเรียกซ้ำด้วยประสิทธิภาพเดียวกัน [1] ในหลายภาษา และใน SICP [2] คุณสามารถดูลูปได้อธิบายว่า "น้ำตาลซินแทติกซ์" ในภาษาโปรแกรมที่จำเป็นที่สุดสำหรับและในขณะที่บล็อกกำลังใช้ขอบเขตเดียวกันกับฟังก์ชั่นหลักของพวกเขา อย่างไรก็ตามในภาษาการเขียนโปรแกรมการทำงานส่วนใหญ่ไม่มีทั้งสำหรับและในขณะที่มีการวนซ้ำเพราะไม่มีความจำเป็นสำหรับพวกเขา
เหตุผลภาษาที่จำเป็นมีสำหรับ / ในขณะที่ลูปคือพวกเขากำลังจัดการกับรัฐโดยการกลายพันธุ์พวกเขา แต่ที่จริงแล้วถ้าคุณมองจากมุมมองที่แตกต่างถ้าคุณคิดว่า a บล็อกในขณะที่ฟังก์ชั่นการรับพารามิเตอร์ประมวลผลและกลับสู่สถานะใหม่ - ซึ่งอาจเป็นการเรียกฟังก์ชั่นเดียวกันกับพารามิเตอร์ที่แตกต่างกัน - คุณ สามารถนึกถึงการวนซ้ำ
โลกอาจนิยามได้ว่าไม่แน่นอนหรือไม่เปลี่ยนรูป ถ้าเรากำหนดโลกเป็นชุดของกฎและเรียกใช้ฟังก์ชั่นสุดท้ายที่ใช้กฎทั้งหมดและสถานะปัจจุบันเป็นพารามิเตอร์และส่งกลับสถานะใหม่ตามพารามิเตอร์เหล่านี้ซึ่งมีฟังก์ชั่นเดียวกัน (สร้างสถานะถัดไปในที่เดียวกัน วิธี) เราก็บอกได้ว่านั่นเป็นการเรียกซ้ำและวนซ้ำ
ในตัวอย่างต่อไปนี้ชีวิตคือฟังก์ชั่นใช้สองพารามิเตอร์ "กฎ" และ "รัฐ" และรัฐใหม่จะถูกสร้างขึ้นในเห็บในครั้งต่อไป
life rules state = life rules new_state
where new_state = construct_state_in_time rules state
[1]: การเพิ่มประสิทธิภาพการโทรแบบหางเป็นการเพิ่มประสิทธิภาพทั่วไปในภาษาโปรแกรมการทำงานเพื่อใช้ฟังก์ชั่นสแต็คที่มีอยู่ในการโทรซ้ำโดยไม่ต้องสร้างใหม่
[2]: โครงสร้างและการตีความของโปรแกรมคอมพิวเตอร์, MIT https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs
ห่วงในขณะที่แตกต่างจากการเรียกซ้ำ
เมื่อเรียกใช้ฟังก์ชันจะมีการดำเนินการดังต่อไปนี้:
เฟรมสแต็กถูกเพิ่มเข้ากับสแต็ก
ตัวชี้รหัสย้ายไปที่จุดเริ่มต้นของฟังก์ชัน
เมื่อลูป while อยู่ที่ท้ายจะเกิดสิ่งต่อไปนี้:
เงื่อนไขถามว่ามีอะไรจริงหรือไม่
ถ้าเป็นเช่นนั้นรหัสจะกระโดดไปยังจุด
โดยทั่วไปห่วง while นั้นคล้ายกับรหัสเทียมต่อไปนี้:
if (x)
{
Jump_to(y);
}
สิ่งที่สำคัญที่สุดของทั้งหมดการเรียกซ้ำและการวนซ้ำมีการแทนรหัสแอสเซมบลีที่แตกต่างกันและการแสดงรหัสเครื่อง ซึ่งหมายความว่าพวกเขาจะไม่เหมือนกัน พวกเขาอาจมีผลลัพธ์เดียวกัน แต่รหัสเครื่องที่แตกต่างกันพิสูจน์ว่าพวกเขาไม่เหมือนกัน 100%
การทำซ้ำเพียงอย่างเดียวนั้นไม่เพียงพอที่จะเทียบเท่ากับการเรียกซ้ำโดยทั่วไป แต่การทำซ้ำด้วยสแต็กจะเทียบเท่าโดยทั่วไป ฟังก์ชันเรียกซ้ำใด ๆ สามารถทำซ้ำโปรแกรมเป็นวนซ้ำด้วยสแต็กและในทางกลับกัน นี่ไม่ได้หมายความว่ามันใช้งานได้จริงและในสถานการณ์ใดรูปแบบหนึ่งหรือในรูปแบบอื่นอาจมีประโยชน์ชัดเจนกว่าเวอร์ชันอื่น
ฉันไม่แน่ใจว่าทำไมสิ่งนี้จึงขัดแย้งกัน การเรียกซ้ำและวนซ้ำด้วยสแต็กเป็นกระบวนการคำนวณเดียวกัน พวกเขาเป็น "ปรากฏการณ์" เดียวกันดังนั้นต้องพูด
สิ่งเดียวที่ฉันคิดได้ก็คือเมื่อมองสิ่งเหล่านี้เป็น "เครื่องมือการเขียนโปรแกรม" ฉันจะยอมรับว่าคุณไม่ควรคิดว่ามันเป็นสิ่งเดียวกัน พวกเขาเป็น "ทางคณิตศาสตร์" หรือ "คำนวณ" เทียบเท่า ( ซ้ำอีกครั้งกับสแต็คไม่ซ้ำโดยทั่วไป) แต่นั่นไม่ได้หมายความว่าคุณควรเข้าหาปัญหาด้วยความคิดที่ทั้งสองจะทำ จากมุมมองของการนำไปใช้งาน / การแก้ปัญหาปัญหาบางอย่างอาจทำงานได้ดีกว่าหรืออีกวิธีหนึ่งและงานของคุณในฐานะโปรแกรมเมอร์คือการตัดสินใจอย่างถูกต้องว่าสิ่งใดเหมาะสมกว่า
หากต้องการชี้แจงให้ชัดเจนคำตอบของคำถามคือขณะที่วนซ้ำแบบวนซ้ำภายในตัวหรือไม่ เป็นที่แน่นอนไม่มีหรืออย่างน้อย "ไม่ได้จนกว่าคุณจะมีสแต็คได้เป็นอย่างดี"