Để trả lời câu hỏi cụ thể của bạn: Không, từ quan điểm của việc học một ngôn ngữ, đệ quy không phải là một tính năng. Nếu giáo sư của bạn thực sự cho điểm bạn vì đã sử dụng một "tính năng" mà ông ấy chưa dạy, điều đó đã sai.
Đọc giữa các dòng, một khả năng là bằng cách sử dụng đệ quy, bạn đã tránh sử dụng một tính năng được cho là kết quả học tập cho khóa học của anh ta. Ví dụ: có thể bạn hoàn toàn không sử dụng phép lặp hoặc có thể bạn chỉ sử dụng for
các vòng lặp thay vì sử dụng cả for
và while
. Thông thường, một bài tập nhằm mục đích kiểm tra khả năng của bạn để làm một số việc nhất định và nếu bạn tránh làm chúng, giáo sư của bạn sẽ không thể cấp cho bạn điểm dành riêng cho tính năng đó. Tuy nhiên, nếu đó thực sự là nguyên nhân khiến bạn bị mất điểm, giáo sư nên coi đây là kinh nghiệm học tập của bản thân - nếu việc chứng minh kết quả học tập nhất định là một trong những tiêu chí cho một bài tập, thì cần giải thích rõ ràng cho sinh viên. .
Phải nói rằng, tôi đồng ý với hầu hết các ý kiến và câu trả lời khác rằng phép lặp là một lựa chọn tốt hơn đệ quy ở đây. Có một vài lý do, và trong khi những người khác đã chạm vào chúng ở một mức độ nào đó, tôi không chắc họ đã giải thích đầy đủ suy nghĩ đằng sau chúng.
Tràn ngăn xếp
Rõ ràng hơn là bạn có nguy cơ gặp lỗi tràn ngăn xếp. Trên thực tế, phương pháp bạn đã viết rất khó thực sự dẫn đến một phương pháp, vì người dùng sẽ phải nhập sai nhiều lần để thực sự kích hoạt tràn ngăn xếp.
Tuy nhiên, một điều cần lưu ý là không chỉ bản thân phương thức, mà các phương thức khác cao hơn hoặc thấp hơn trong chuỗi cuộc gọi sẽ nằm trên ngăn xếp. Bởi vì điều này, việc vô tình chiếm đoạt không gian ngăn xếp có sẵn là một điều khá bất lịch sự đối với bất kỳ phương pháp nào. Không ai muốn phải thường xuyên lo lắng về không gian ngăn xếp trống bất cứ khi nào họ viết mã vì rủi ro rằng mã khác có thể đã sử dụng quá nhiều không cần thiết.
Đây là một phần của nguyên tắc chung hơn trong thiết kế phần mềm được gọi là trừu tượng hóa. Về cơ bản, khi bạn gọi DoThing()
, tất cả những gì bạn cần quan tâm là Điều đã xong. Bạn không cần phải lo lắng về các chi tiết triển khai về cách nó được thực hiện. Nhưng việc sử dụng ngăn xếp một cách tham lam đã phá vỡ nguyên tắc này, bởi vì mỗi bit mã phải lo lắng về số lượng ngăn xếp mà nó có thể an toàn giả định rằng nó đã để lại cho nó bằng mã ở nơi khác trong chuỗi lệnh gọi.
Dễ đọc
Lý do khác là tính dễ đọc. Lý tưởng mà mã nên mong muốn là trở thành một tài liệu có thể đọc được của con người, trong đó mỗi dòng mô tả đơn giản những gì nó đang làm. Thực hiện hai cách tiếp cận sau:
private int getInput() {
int input;
do {
input = promptForInput();
} while (!inputIsValid(input))
return input;
}
đấu với
private int getInput() {
int input = promptForInput();
if(inputIsValid(input)) {
return input;
}
return getInput();
}
Vâng, cả hai đều hoạt động và có, cả hai đều khá dễ hiểu. Nhưng hai cách tiếp cận có thể được mô tả bằng tiếng Anh như thế nào? Tôi nghĩ nó sẽ giống như:
Tôi sẽ nhắc nhập cho đến khi đầu vào hợp lệ rồi trả lại
đấu với
Tôi sẽ nhắc nhập đầu vào, sau đó nếu đầu vào hợp lệ tôi sẽ trả lại, nếu không, tôi sẽ nhận đầu vào và trả về kết quả của điều đó
Có lẽ bạn có thể nghĩ về những từ ngữ ít rườm rà hơn cho phần sau, nhưng tôi nghĩ bạn sẽ luôn thấy rằng từ đầu tiên sẽ là một mô tả chính xác hơn, về mặt khái niệm, về những gì bạn thực sự đang cố gắng làm. Điều này không có nghĩa là đệ quy luôn luôn khó đọc hơn. Đối với các tình huống mà nó tỏa sáng, chẳng hạn như duyệt qua cây, bạn có thể thực hiện cùng một loại phân tích song song giữa đệ quy và một cách tiếp cận khác và gần như chắc chắn bạn sẽ thấy đệ quy cung cấp mã tự mô tả rõ ràng hơn, từng dòng một.
Riêng biệt, cả hai đều là những điểm nhỏ. Rất ít khả năng điều này sẽ thực sự dẫn đến tràn ngăn xếp và khả năng đọc đạt được là rất nhỏ. Nhưng bất kỳ chương trình nào cũng sẽ là tập hợp của nhiều quyết định nhỏ này, vì vậy, ngay cả khi chúng tách rời nhau không quan trọng nhiều, điều quan trọng là phải tìm hiểu các nguyên tắc đằng sau việc làm cho chúng đúng.