什么事? 我和Prolog有一些非常奇怪的问题 在给定索引处替换列表中元素的递归规则并不总是有效 我的规则如下:
% Base rule - Stops when index is 1 and replaces the head with the element.
replaceAtIndex(1, _element, [_|_tail], [_element|_tail]).
% Recursive rule - Enter recursion for tail as long as index is larger than 1.
replaceAtIndex(_index, _element, [_head|_tail], [_head|_new_tail]):-
_index > 1,
_new_index is _index - 1,
replaceAtIndex(_new_index, _element, _tail, _new_tail).
当我在我的程序中使用调试器时,我看到它始终调用第二条规则,无论索引是什么,但是当我在程序外执行完全相同的命令时,它运行得非常好。它到达索引1但是调用第二个规则,并且没有回溯并尝试第一个规则并且一直失败...
调用replaceAtIndex的规则如下所示:
level_replace_block_value(_x, _y, _value):-
current_level(_level_number, _width, _height, _blocks, _drawX, _drawY),
coordinates_to_index(_x, _y, _index),
_index_in_list is _index + 1, % the replaceAtIndex is not 0 terminated
replaceAtIndex(_index_in_list, _value, _blocks, _new_blocks),
retractall(current_level(_,_,_,_,_,_)),
assert(current_level(_level_number, _width, _height, _new_blocks, _drawX, _drawY),
graphics_update_block_value(_x, _y).
当我调试索引为111的调用时。
当我用常数111替换_index_in_list
时,它可以工作。
任何人都可能知道为什么会这样?
答案 0 :(得分:1)
使用内置谓词&
,<select name='cat1'>
<option value='0'>Select one</option>
<option value='1'>little</option>
<option value='2'>good</option>
</select>
<select name='soft1'>
<option value=''>Select one</option>
<option value='W'>Word</option>
<option value='E'>Excel</option>
<option value='PP'>Power Point</option>
</select>
<br />
<select name='cat2'>
<option value='0'>Select one</option>
<option value='1'>little</option>
<option value='2'>good</option>
</select>
<select name='soft2'>
<option value=''>Select one</option>
<option value='W'>Word</option>
<option value='E'>Excel</option>
<option value='PP'>Power Point</option>
</select>
<br />
<br />
和same_length/2
保留logical-purity!
length/2
首先,让我们在a previous answer中运行@magus用于此问题的示例查询:
append/3
以后实例化列表项时是否有效?
replace_at(I,X,Xs0,Xs2) :-
same_length(Xs0,Xs2),
append(Prefix,[_|Xs1],Xs0),
length([_|Prefix],I),
append(Prefix,[X|Xs1],Xs2).
是的!如果索引不是具体的整数,而是未绑定的逻辑变量,该怎么办? 那有用吗?
?- replace_at(3,0,[1,2,3,4,5,6],Xs).
Xs = [1,2,0,4,5,6] ;
false.
确实如此!使用单调代码,即使是非常常见的查询,我们也能获得逻辑上合理的答案。
答案 1 :(得分:0)
我怀疑你误解了回溯发生的方向。
第一个&#34;基地&#34;对replaceAtIndex/4
的任何调用都将首先尝试规则。如果失败,由于与&#34; head&#34;的呼叫不一致。第一条规则,然后Prolog引擎回溯到第二条规则。 [统一失败可能来自第一个参数(索引)不同于1或第三个参数不是非空列表。]
回溯永远不会走向另一个方向。如果第二条规则尝试失败,则呼叫失败。
当然,递归定义使事情复杂化。应用第二条规则的成功需要对replaceAtIndex/4
进行新的调用,就Prolog引擎而言,必须从第一条规则开始尝试满足该目标。
我建议在第一条规则中添加一个剪切,因为按照构造,第二条规则永远不会成功。但这只是一个效率问题......为什么要让选择点保持开放,永远不会产生任何进一步的解决方案呢?
replaceAtIndex(1, _element, [_|_tail], [_element|_tail]) :- !.
已添加:我确认您的代码在Amzi中有效! Prolog这样的电话:
?- replaceAtIndex(3, 0, [1,2,3,4,5,6], L).
L = [1, 2, 0, 4, 5, 6] ;
no
?-
但是当你以独立/解释模式调用代码时,你也会看到成功。
所以我不得不怀疑&#34;索引&#34;传入的参数不是整数,而是浮点数。整数1不会与浮点1.0统一,即使它们在数学上是相等的。
您可以使用谓词 is_integer / 1 在Amzi中对此进行测试!序言。函数整数(X)可用于通过截断(不存在的)小数部分将实数1.0转换为整数1。
答案 2 :(得分:-1)
将_index_in_list
设置为1
。那么第一条规则不会被调用吗?
如果您的_index_in_list
为111
,111
大于1
,请确保调用第二条规则的原因是什么?第一条规则只处理1
- 作为第一个参数说明。
当我用常量
_index_in_list
替换111
时 的工作原理。
什么?你的意思是第一个规则被调用?怎么可能,第一个参数是1
。
答案 3 :(得分:-1)
replaceAtIndex(I, Value, List, Result) :-
RI is I-1,
findall(Before, (nth0(B, List, Before), B < RI), Before),
findall(After, (nth0(A, List, After), A > RI), After),
append([Before, [Value], After], Result).
?- replaceAtIndex(3,0,[1,2,3,4,5,6], L).
L = [1, 2, 0, 4, 5, 6].