[解決済み] Lispで再帰関数はどのように動作するのですか?
2022-02-25 06:22:01
質問
Lispでコーディングしているのですが、リスト(サブリストなし)内のアトムの数を数える関数を思いつきました。
(defun num-atoms (list)
(cond
((null list) 0)
((atom list) 1)
(t (+ (num-atoms (car list))
(num-atoms (cdr list))))))
で、これは動作し、私には意味があります。では、この関数をリストで呼び出すと
(1 2 3)
を引数に取ると、次のようになるはずです。
- (num-atoms '(1 2 3))
- nullでない
- not atom
- num-atoms(1)
- アトムなので1を返す
- num-atoms ((2 3))
- nullでない
- not atom
- num-atoms (2)
- 1を返す
- ....
- などなど
しかし、このようにコードを書くと
(defun num-atoms (list)
(cond
((null list) 0)
((atom list) 1)
(t (+ (num-atoms (cdr list))
(num-atoms (car list))))))
ここで、最後の行でde carとcdrの位置を入れ替えただけです。
そして、トレースすると、同じ順番で原子の数が表示されます!'(1 2 3)リストの中で1が最初にカウントされ、以下同様です。 どなたか、この2番目のバージョンのコードがどのように動作するのか、説明していただけませんか?このロジックは本当に理解できません。
どのように解決するのですか?
もし、あなたが トレース の2つの関数がどのように異なるかがわかると思います。
最初のバージョンでは、この関数は最初の要素 (
car
)、そして残りの要素(
cdr
).
2番目のバージョンでは、関数はまず最初の要素を処理する前に残りの要素を処理するため、アトムは逆の順序で処理されます。つまり、最初に見つかったアトムはリストの最後となり、その後、スタックが巻き戻されます。
しかし、足し算はあくまで足し算なので、結果はもちろんどちらも同じです。 可換 .
* (defun num-atoms(list)
(cond
((null list) 0)
((atom list) 1)
(t (+ (num-atoms (car list)) (num-atoms (cdr list))))))
NUM-ATOMS
* (trace num-atoms)
(NUM-ATOMS)
* (num-atoms '(1 2 3))
0: (NUM-ATOMS (1 2 3))
1: (NUM-ATOMS 1)
1: NUM-ATOMS returned 1
1: (NUM-ATOMS (2 3))
2: (NUM-ATOMS 2)
2: NUM-ATOMS returned 1
2: (NUM-ATOMS (3))
3: (NUM-ATOMS 3)
3: NUM-ATOMS returned 1
3: (NUM-ATOMS NIL)
3: NUM-ATOMS returned 0
2: NUM-ATOMS returned 1
1: NUM-ATOMS returned 2
0: NUM-ATOMS returned 3
3
そして
* (defun num-atoms(list)
(cond
((null list) 0)
((atom list) 1)
(t (+ (num-atoms (cdr list)) (num-atoms (car list))))))
NUM-ATOMS
* (num-atoms '(1 2 3))
0: (NUM-ATOMS (1 2 3))
1: (NUM-ATOMS (2 3))
2: (NUM-ATOMS (3))
3: (NUM-ATOMS NIL)
3: NUM-ATOMS returned 0
3: (NUM-ATOMS 3)
3: NUM-ATOMS returned 1
2: NUM-ATOMS returned 1
2: (NUM-ATOMS 2)
2: NUM-ATOMS returned 1
1: NUM-ATOMS returned 2
1: (NUM-ATOMS 1)
1: NUM-ATOMS returned 1
0: NUM-ATOMS returned 3
3
*
関連
-
[解決済み】再帰使用時のOcamlエラーUnbound Value
-
[解決済み] 再帰使用時のOcaml Error Unbound Value
-
[解決済み] 再帰的な関数をフローチャートで表現するには?
-
[解決済み] 最後の関数の再帰呼び出しで「scheme application not a procedure」と表示された
-
[解決済み] Fatal error.の解決方法 PHPの「Fatal error: Maximum function nesting level of '100' reached, aborting!
-
[解決済み] Schemeにおける再帰的関数
-
[解決済み] Lispで再帰関数はどのように動作するのですか?
-
[解決済み] 再帰とループの比較
-
[解決済み] 再帰から反復への道
-
[解決済み] 再帰性はそれ自体が特徴なのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] リストを反転させるにはどうしたらいいですか?
-
[解決済み] 再帰的な関数をフローチャートで表現するには?
-
[解決済み] 最後の関数の再帰呼び出しで「scheme application not a procedure」と表示された
-
[解決済み] Fatal error.の解決方法 PHPの「Fatal error: Maximum function nesting level of '100' reached, aborting!
-
[解決済み] Schemeにおける再帰的関数
-
[解決済み] Lispで再帰関数はどのように動作するのですか?
-
[解決済み] 再帰とループの比較
-
[解決済み] 再帰から反復への道
-
[解決済み] foldrとfoldl(またはfoldl')の意味するところ
-
[解決済み] 再帰性はそれ自体が特徴なのか?