再帰的な関数呼び出しの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ステートメントの意味がわかりません(つまり、research search_list(l-> next、x))。誰もがスタックモデルを使用してこの概念を説明できれば、本当に役立ちます。


リストの最初の用語が結果でない場合、リストの残りを検索します。これが最後のreturn機能です。
ジョルジオ

@Giorgio、なぜ関数呼び出しだけで十分ではないのですか、その前にリターンが必要なのはなぜですか?
user1369975

7
関数によって返される値を返す必要があるため
Esailija

7
Downvoters:OPの背景に応じて、何returnが行われるのかはまったく明らかではないことに注意してください。実際、関数型言語(およびScalaのような混合言語)return では必要ありません。再帰関数の値は、その最後の式の値です。Scalaで作業していsearch_list(l->next, x)なければ、書く必要returnはありません。returnステートメントの意味は、命令的な背景を持つプログラマーにのみ明らかです。
アンドレスF.

OP:コードスニペットはCで書かれていますか?
アンドレスF.

回答:


19

returnステートメントは、現在の関数の呼び出しフレームの直接の呼び出し元に値を返します。再帰の場合、この直接の呼び出し元は、同じ関数の別の呼び出しになる可能性があります。

ほとんどの言語では、呼び出した関数の戻り値を(再帰的にまたは再帰的に)使用しない場合、その戻り値は破棄されるか、診断可能なエラーです。最後の関数呼び出しの戻り値が現在の関数呼び出しの戻り値として自動的に再利用される言語もありますが、通常の関数呼び出しと再帰的な関数呼び出しは区別されません。

次のようなコードを記述した場合、未使用の戻り値は暗黙のうちに破棄されます。

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は最後の式の結果を自動的に返します。これは、戻り値を再利用することを意味すると思います。しかし、私は何年もそれに触れていないので、私はそれを確信していません。
ボブソン

1

2つのこと; 探している「x」が見つかった場合にリスト全体を返すことは必ずしも再帰の使用を保証するものではありませんが、それ以外に次のことを考慮してください。

X = "December"の値を探していて、リストがその年の月の数値であり、次の月へのポインタであり、リスト内のl-> itemsが綴られた名前であるとしますヶ月。(1月、2月、...、12月)。可能性のある結果を得るには、3つのリターンが必要です。リストに探しているXが含まれていない場合、最初のreturn(NULL)が必要です。2番目の(return(l))はリストを返します。この場合、「x」が見つかったことを知らせます。最後は、スタックモデルが作用する場所です。関数を連続して呼び出すと、次のようにローカル変数(具体的にはl-> item)が更新されます。

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.

あなたのイラストに感謝しますが、実際には最後のリターンを使用しないでください
-user1369975

最後の復帰がなければ、ステップ1を過ぎてしまうことはありません。
panhandel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.