Причина, по которой это происходит, заключается в том, что в первом случае все еще есть " возможность " для возврата, тогда как во втором случае такой возможности нет.
Если мы назовем цельс помощью trace
мы видим:
[trace] ?- can_use(judy, vb).
Call: (8) can_use(judy, vb) ? creep
Call: (9) access(judy, _2968) ? creep
Exit: (9) access(judy, comp1) ? creep
Call: (9) can_run(comp1, vb) ? creep
Call: (10) spec(comp1, _2968, _2970) ? creep
Exit: (10) spec(comp1, pc, 32) ? creep
<b>Call: (10) runs(pc, vb, _2970) ? creep</b>
Exit: (10) runs(pc, vb, 16) ? creep
Call: (10) 32>=16 ? creep
Exit: (10) 32>=16 ? creep
Exit: (9) can_run(comp1, vb) ? creep
Exit: (8) can_use(judy, vb) ? creep
true ;
<b>Redo: (10) runs(pc, vb, _2970)</b> ?
Мы, таким образом, делаем вызов runs/3
с runs(pc, vb, MemNeeded)
, и Пролог находит первый ответ с 16
.Но он устанавливает точку возврата для поиска других runs/3
фактов с runs(pc, vb, MemNeeded)
.Представьте, что позже в исходном коде есть еще один факт, например runs(pc, vb, 14)
в конце, тогда это может дать другой ответ.
Если мы, однако, назовем вторую цель, мы увидим:
[trace] ?- can_use(david, prolog).
Call: (8) can_use(david, prolog) ? creep
Call: (9) access(david, _3726) ? creep
Exit: (9) access(david, comp1) ? creep
Call: (9) can_run(comp1, prolog) ? creep
Call: (10) spec(comp1, _3726, _3728) ? creep
Exit: (10) spec(comp1, pc, 32) ? creep
Call: (10) runs(pc, prolog, _3728) ? creep
Fail: (10) runs(pc, prolog, _3728) ? creep
Fail: (9) can_run(comp1, prolog) ? creep
Redo: (9) access(david, _3726) ? creep
Exit: (9) access(david, comp2) ? creep
Call: (9) can_run(comp2, prolog) ? creep
Call: (10) spec(comp2, _3726, _3728) ? creep
Exit: (10) spec(comp2, mac, 128) ? creep
<b>Call: (10) runs(mac, prolog, _3728) ? creep</b>
Exit: (10) runs(mac, prolog, 128) ? creep
Call: (10) 128>=128 ? creep
Exit: (10) 128>=128 ? creep
Exit: (9) can_run(comp2, prolog) ? creep
Exit: (8) can_use(david, prolog) ? creep
true.
Здесь мы называем runs(mac, prolog, MemNeeded).
, и это последний факт runs/3
, поэтому нет другой возможности удовлетворить runs/3
в противном случае: поскольку Пролог работает сверху вниз, если мы выполнили последний факт /мы знаем, что другой опции нет.
Поскольку все другие вызовы также принимают последний предикат, или с другой константой в качестве первого параметра (SWI-Prolog просматривает первый аргумент, когда компилируетисходный код в качестве оптимизации), нет никаких других точек возврата, и, таким образом, нет никакого способа Redo
определенного вызова.