2011-11-27 7 views
0
del(X,[X|Reszta],Reszta). 
del(X,[Y|Ogon],[Y|Reszta]) :- del(X,Ogon,Reszta). 

이 코드를 이해하지 못합니다. 내가 묻는다면 :목록에서 요소 제거

?- del(c, [a,b,c],X). 

컴파일러는 두 번째 줄에 갈 것이다, 그는 재귀 루프 del(x,[b,c],[])을 트리거합니다. 내가 맞습니까?

답변

1

당신은 통역을 입력하여 작동하는 방법 (적어도 SWI-PL에, 음, 다른 구현에서 비슷한해야한다) 볼 수는 :

?- trace, del(c, [a,b,c],X). 

BTW, 당신은 확실히 같은 줄을 포함하는 것을 잊었다 :

del(_, [], []). 

그렇지 않으면 알고리즘이 결과 목록을 초기화하지 않습니다.
다음은 정말 기본입니다. 목록의 첫 번째 요소가 제거하려는 요소와 통합 가능하면 건너 뜁니다. 그렇지 않으면 결과 목록에 포함합니다. basicly 여기에서 매우

, 그와 같이 동작한다 :의리스트를 생성 할 때
가 델 (c, [A, B, C, X는) =>를 단일화 할 수없는 C 우리는를 포함 끝.
del (c, [b, c], X) => c는 b와 통합 할 수 없으므로 끝에있는 목록을 구성 할 때 b를 포함합니다.
del (c, [c], X) => c는 c와 통합 될 수 있으므로 목록을 구성 할 때 c를 포함하지 않습니다.
X = [] 일 때 del (c, [], X) => []가 참이므로 X = []라고 가정하고 이제 재귀를 등반하여 결과 목록을 구성 해 보겠습니다 :
X = c가 포함되지 않았으므로 한 단계 올라간다.
X = [b] b가 포함되어 있기 때문에 한 걸음 올라갈 때.
a가 포함되어 있기 때문에 한 단계 올라갈 때 X = [a, b].

1

무슨 일이 발생하는지 보려면 trace/0을 사용하십시오. 이 경우 :에서

4 ?- trace. 
true. 

[trace] 4 ?- del(c,[a,b,c],X). 
    Call: (6) del(c, [a, b, c], _G531) ? creep 
    Call: (7) del(c, [b, c], _G607) ? creep 
    Call: (8) del(c, [c], _G610) ? creep 
    Exit: (8) del(c, [c], []) ? creep 
    Exit: (7) del(c, [b, c], [b]) ? creep 
    Exit: (6) del(c, [a, b, c], [a, b]) ? creep 
X = [a, b] . 

각각 첫 번째 요소는 우리가 제거하고 싶은 경우 "설정"프롤로그가 확인합니다. 그렇다면,하고 있습니다. 그렇지 않으면, 우리는 머리를 유지하고 반복적으로 목록 요소가 주어진 목록에없는 경우 우리가 무슨 일에 대해 생각해야하는지 여부를

의 꼬리 델/3를 호출 할 또 다른 문제입니다; 우리는 그 경우에 술어가 실패하기를 원할 수도 있습니다. 우리는 전체리스트를 반환하기를 원할 것입니다. 그리고 나서 del(_, [], []).을 덧셈으로 추가해야합니다.