2012-07-09 2 views
2

나는 프롤로그로 시작하는거야, 그리고 난 혼란 조금 해요 ... 나는 간단한 프로그램이 SWI - 프롤로그 : 합계-목록

:

sum(0, []). 
sum(Total, [Head|Tail]) :- sum(Sum, Tail), Total is Head + Sum. 

내가 디버깅 할 때, 내가 수를 Prolog는 먼저 Head와 Tail을 사용하여 목록을 나눕니다. 따라서 결과는 0 + 빈 목록이며, 숫자가 합쳐지기 시작한 후 다시 목록에 추가됩니다.

누군가가 왜 Total is Head + Sum. 에 오지 않았는지 설명하고 머리와 꼬리로 다시 목록을 나눌 수 있습니까?

편집 :

[trace] ?- sum(X, [1,2,3]). 
Call: (6) sum(_G345, [1, 2, 3]) ? creep 
Call: (7) sum(_G424, [2, 3]) ? creep 
Call: (8) sum(_G424, [3]) ? creep 
Call: (9) sum(_G424, []) ? creep 
Exit: (9) sum(0, []) ? creep 
Call: (9) _G430 is 3+0 ? creep 
Exit: (9) 3 is 3+0 ? creep 
Exit: (8) sum(3, [3]) ? creep 
Call: (8) _G433 is 2+3 ? creep 
xit: (8) 5 is 2+3 ? creep 
Exit: (7) sum(5, [2, 3]) ? creep 
Call: (7) _G345 is 1+5 ? creep 
Exit: (7) 6 is 1+5 ? creep 
Exit: (6) sum(6, [1, 2, 3]) ? creep 
X = 6. 

답변

5

귀하의 정의는 스택에 추가를두고 다음은 추적이다. 덧셈을 피하는 최적화는 꼬리 재귀으로 알려진 일반적인 기술의 특수한 경우입니다. 그것은 부분 합계 값에 대한 축적을 소개하고리스트의 테일로 운반

sum(X,L):-sum(0,L,X). 
sum(X,[],X). 
sum(N, [Head|Tail],Y) :- N1 is Head + N, sum(N1,Tail,Y). 

:

다음 정의는 꼬리 재귀를 사용할 수있다. 다음은 sum(X,[1,2,3]) 쿼리의 실행 추적입니다.

?- trace, sum(S,[1,2,3]),notrace,nodebug. 
    Call: (7) sum(_G584, [1, 2, 3]) ? creep 
    Call: (8) sum(0, [1, 2, 3], _G584) ? creep 
^ Call: (9) _G792 is 1+0 ? creep 
^ Exit: (9) 1 is 1+0 ? creep 
    Call: (9) sum(1, [2, 3], _G584) ? creep 
^ Call: (10) _G795 is 2+1 ? creep 
^ Exit: (10) 3 is 2+1 ? creep 
    Call: (10) sum(3, [3], _G584) ? creep 
^ Call: (11) _G798 is 3+3 ? creep 
^ Exit: (11) 6 is 3+3 ? creep 
    Call: (11) sum(6, [], _G584) ? creep 
    Exit: (11) sum(6, [], 6) ? creep 
    Exit: (10) sum(3, [3], 6) ? creep 
    Exit: (9) sum(1, [2, 3], 6) ? creep 
    Exit: (8) sum(0, [1, 2, 3], 6) ? creep 
    Exit: (7) sum(6, [1, 2, 3]) ? creep 
S = 6 . 
-2

여기에는 다른 버전이 있습니다. 나는 코드 설계에 도움이되는 개념 매핑 소프트웨어를 사용해 왔지만, 나는 머리 속에 복잡한 일을 할 수 없다.

sum(A, [], A). 
sum(Total, [Head|Tail], AuxNum) :- 
    Sum is Head+AuxNum, 
    sum(Total, Tail, Sum). 


    1 ?- trace,sum(Total,[1,2,3],0). 
    Call: (7) sum(_G2090, [1, 2, 3], 0) ? creep 
    Call: (8) _G2221 is 1+0 ? creep 
    Exit: (8) 1 is 1+0 ? creep 
    Call: (8) sum(_G2090, [2, 3], 1) ? creep 
    Call: (9) _G2224 is 2+1 ? creep 
    Exit: (9) 3 is 2+1 ? creep 
    Call: (9) sum(_G2090, [3], 3) ? creep 
    Call: (10) _G2227 is 3+3 ? creep 
    Exit: (10) 6 is 3+3 ? creep 
    Call: (10) sum(_G2090, [], 6) ? creep 
    Exit: (10) sum(6, [], 6) ? creep 
    Exit: (9) sum(6, [3], 3) ? creep 
    Exit: (8) sum(6, [2, 3], 1) ? creep 
    Exit: (7) sum(6, [1, 2, 3], 0) ? creep 
Total = 6. 
+0

이것은 Dmitri의 버전과 의미가 다르지 않습니다. –