2017-05-12 1 views
1

문제가있는 프로그램을 만들고 있습니다. 이 짧은 예에서 오류가 동일합니다무한 루프에서 길을 잃었습니다

편집코드가 잘못

does_something(A, [Num], Sol) :- 
    sort([Num|A], Sol). 

correct(Solution) :- 
    Solution = [1,2,3,4,5]. 

pred1(_, Solution, Solution) :- correct(Solution), !. 
pred1(A, B, Solution) :- 
    member(Num, A), 
    does_something(B, [Num], B_aux), 
    pred1(A, B_aux, Solution). 

마지막 편집 : 내가 원하는 것은 술어가 does_something하고 정확한 함께 할 수 없다. 그것들은 예제를위한 것일 뿐이며, 그것들은 문제와 아무 관련이 없습니다. 내가 원하는 것은 Num로 술어 does_something을 호출하는 것이 올바른 해결책을 제시 하는지를 아는 것입니다. 그렇지 않으면 솔루션을 찾을 때까지 A의 다른 구성원을 시도하도록 고안되었습니다. 절대로 실패하지 않는다면 문제 없습니다. 내 문제는 내가 A.

?- pred1([1,2,3], [], S). 

Call: (9) [user] does_something([1], [1], _G6045) ? creep 
Call: (10) [system] sort([1, 1], _G6047) ? creep 
Exit: (10) [system] sort([1, 1], [1]) ? creep 
Exit: (9) [user] does_something([1], [1], [1]) ? creep 
Call: (9) [user] pred1([1, 2, 3], [1], _G5943) ? creep 
Call: (10) [user] correct([1]) ? creep 
Call: (11) [system] [1]=[1, 2, 3, 4, 5] ? creep 
Fail: (11) [system] [1]=[1, 2, 3, 4, 5] ? creep 
Fail: (10) [user] correct([1]) ? creep 
Redo: (9) [user] pred1([1, 2, 3], [1], _G5943) ? creep 
Call: (10) [lists] lists:member(_G6052, [1, 2, 3]) ? creep 
Exit: (10) [lists] lists:member(1, [1, 2, 3]) ? creep 
Call: (10) [user] does_something([1], [1], _G6057) ? creep 

트레이스 부분의 처음과 마지막 라인이 동일한에 처음보다 또 다른 민 호출 할 수 does_something 할 수 없다는 것입니다.

+0

추적을 표시 할 수 있습니까? 프로그램의 전체 소스가 도움이 될 수도 있습니다. 그러나 이상적으로는 오류를 재생산하는 최소한의 완전한 예제를 찾아야합니다. [MCVE] (https://stackoverflow.com/help/mcve)를 참조하십시오. –

+0

예제를 작성해 보겠습니다. –

+0

** 전체 프로그램을 보여주세요! 그렇지 않으면 모두 추측입니다. – false

답변

3

명확한 문제는 A이 변경되지 않는다는 것입니다. 즉, 재귀의 각 단계에서 member(_GXXX, [1, 2, 3])을 계속 호출하면 첫 번째 요소 인 1이 선택됩니다. 목록에 추가하고 정렬하는 경우 1을 추가하고 정렬 만하므로 B[1]에 있습니다.

이것은 사용자 코드가하는 것입니다. 당신이 달성하고자하는이, 또 다른 질문, 그리고 정말 BTW

:-(이 코드보고에서 당신의 의도를 추측 할 수 없습니다

append(A, [X], A1), sort(A1, B) 

것과 같은 효과가 있어야한다 당신은 당신이 append/3을 사용할 때 목록을 통과하지 않아도 작은 차이
sort([X|A], B) 

. (append/3 정말 목록을 추가하는 데 사용하는 것과, 다른 뭔가라고되어 있어야하는 것은 일반적으로 필요하지 않습니다. 그것은 비록 분할에 유용합니다. ..)

추 신 : 목록에서 한 요소를 계속 가져오고 싶다면 가장 쉬운 방법은 첫 번째 요소를 선택하는 것입니다. 이렇게하는 술어는 다음과 같습니다.

foo([], Result, ...). 
foo([X|Xs], R, ...) :- 
    foo(Xs, [X|R], ...). 

그래서 한 요소를 선택하여 다른 목록에 넣으면됩니다. 이에 대해서는 member/2이 필요하지 않습니다. 또는 select/3을 사용하여 요소를 가져올 수있을뿐만 아니라 나머지 항목의 목록을 제공 할 수도 있습니다. 그러나 :

bar([], R, ...). 
bar(Xs, R, ...) :- 
    select(X, Xs, Xs0), 
    bar(Xs0, [X|R], ...). 

위의 foo과 동일합니다.

+0

swi 터미널에 다음과 같이 쓰면 member (Num, [1,2,3]), writeln (Num), 실패하면 3 개의 숫자가 쓰여지고 false가됩니다. 이 경우 왜 술어 구성원이 각 실패시 번호를 변경하고 있으며 제 경우에는 그렇지 않습니다. –

+0

@DavidNunes 당신의 프리디 케이트 정의에'fail'이 없기 때문에 그렇습니까? –

+0

@DavidNunes 프로그램이하는 일을 관찰하는 것이 하나 있습니다. 이유를 아는 또 다른 일. 다른 일을하는 다른 프로그램을 작성하는 방법을 이해해야합니다. –

관련 문제