Что случилось?
У меня очень странные проблемы с Прологом.
Рекурсивное правило замены элемента в списке по заданному индексу не всегда работает.
Мое правило выглядит так:
% 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.
Когда я заменяю _index_in_list
константой 111, это работает.
Кто-нибудь может подсказать, почему так происходит?
replaceAtIndex
, который действительно ведет себя так, как вы описываете? В идеале без использованияlevel_replace_block_value
. Может быть, проблема в том, что две ссылки на_tail
(или_element
) не могут быть объединены? - person svick   schedule 09.02.2012p(1).
, и вы запросите?- X is 2 - 1, p(X).
? - person Nick Barnes   schedule 09.02.2012doReplace(2, _new_list).
дает_new_list = [0,1,10,3,4,5] ; no ?-
Не удается воссоздать это: - person YLivay   schedule 09.02.2012replaceAtIndex(I,...) :- ( I == 1 -> ... ; ... ).
и посмотрите, приведет ли это к другому поведению. - person twinterer   schedule 09.02.2012_index
... возможно, ваш интерпретатор выполняет глупую оптимизацию. Это стандартное соглашение для НЕИСПОЛЬЗУЕМЫХ переменных. - person Volker Stolz   schedule 09.02.2012is/2
только для арифметической оценки._new_tail is tail
не получится. - person twinterer   schedule 09.02.2012replaceAtIndex(I,E,[H|T],[NH|NT]) :- ( I==1 -> NH=E,NT=T ; NH=H,I1 is I-1,replaceAtIndex(I1,E,T,NT) ).
- person twinterer   schedule 09.02.2012