トレースしましょう:
?- trace, del(5, [3,4,5,6,7], X).
Call: (7) del(5, [3, 4, 5, 6, 7], _G218) ? creep
Call: (8) 5\=3 ? creep
Exit: (8) 5\=3 ? creep
Call: (8) del(5, [4, 5, 6, 7], [_G344]) ? creep
Call: (9) 5\=4 ? creep
Exit: (9) 5\=4 ? creep
Call: (9) del(5, [5, 6, 7], [[]]) ? creep
Fail: (9) del(5, [5, 6, 7], [[]]) ? creep
Fail: (8) del(5, [4, 5, 6, 7], [_G344]) ? creep
Fail: (7) del(5, [3, 4, 5, 6, 7], _G218) ? creep
false.
したがって、コードが 5 になると実際には失敗していることがわかります5 \= 5
。リストに複数の項目があるため、最初のルールは一致しません。5 \= 3
2 番目のルールはandを見つけた後に「正しく」繰り返され5 \= 4
ますが、どのルールにもケースがない5 = 5
ため、そこで失敗が発生します。
ちなみに、リストに 5 がない場合はどうなるか見てみましょう。
?- trace, del(5, [3,4,6,7], X).
Call: (7) del(5, [3, 4, 6, 7], _G350) ? creep
Call: (8) 5\=3 ? creep
Exit: (8) 5\=3 ? creep
Call: (8) del(5, [4, 6, 7], [_G473]) ? creep
Call: (9) 5\=4 ? creep
Exit: (9) 5\=4 ? creep
Call: (9) del(5, [6, 7], [[]]) ? creep
Fail: (9) del(5, [6, 7], [[]]) ? creep
Fail: (8) del(5, [4, 6, 7], [_G473]) ? creep
Fail: (7) del(5, [3, 4, 6, 7], _G350) ? creep
false.
これが、前に「正しく」と言った理由です。あなたの帰納的なケースも正しくありません。1つには、del(Ele, T, [New])
持っているのに上にあるdel(Ele, [H|T], [H|New])
ので、右側で余分な時間をかけてリストをアンラップしています (これが私たちのトレースが含ま[[]]
れている理由です)。しかし、@false は、削除しようとしているものを実際に見つけた場合をまったく考慮しないという、より大きな問題に直面します。:)リストが空の場合も処理しません。
データ構造をたどって各項目を調べることが O(N) になるというのは、残念なことです。もう 1 つの残念な事実は、関数型言語と宣言型言語 ( 「代入可能言語」がない言語) では、リストを変更することはリストの少なくとも一部をコピーすることを意味します。Prolog でこれを行うには、より効率的な方法があります (たとえば、差分リストを使用できます) が、基本的な問題は同じです。Prolog の効率性はかなり大きなトピックです。前もってあまり心配しないように言っておきますが、すぐに気になることがあります。しかし、この場合、いいえ、破壊的な更新を使用した実質的により効率的なアプローチは実際にはありません。