2013-03-28 9 views
0

Я использую интерпретатор Prolog в OCaml. Проблема, с которой я столкнулся, заключается в основной функции. Я по существу стараюсь хранить стек интерпретатора в вызове функции и модифицировать копию этого стека, которая затем передается в рекурсивный вызов из этого конкретного вызова функции. Когда этот рекурсивный вызов сообщает об ошибке, этот оригинальный вызов функции должен использовать исходный стек, который я сохранил без изменений, и сделать другой рекурсивный вызов (для реализации обратного отслеживания).Стек автоматически изменяется, когда он не должен

Теперь вот в чем проблема. Стек и временный стек (tempstack) оба изменяются, когда я намерен только изменить tempstack. Я потратил часы, пытаясь понять проблему, и я уверен, что это все. Вот основная функция сниппет ..

let rec main stack clauselist counter substitutions variablesinquery answers = 
try 
    let currentsubgoal = Queue.top (Stack.top stack) in 
    if counter <> List.length clauselist 
    then 
     let tempstack = Stack.copy stack in 
     try 
      let unifier = mgu1 currentsubgoal (List.nth clauselist counter) in 
      let newsubgoals = 
       match List.nth clauselist counter with 
        Fact(a) -> [] 
       | Rule(Headbody(a,b)) -> b 
      in 
      let tempstack = stacknewsubgoals tempstack unifier newsubgoals in 
      let tempsubs = match substitutions with 
       S(m) -> match unifier with S(n) -> S(m @ n) in 
      try 
       main tempstack clauselist 0 tempsubs variablesinquery answers 
      with BackTrack -> main stack clauselist (counter + 1) substitutions 
               variablesinquery answers 
     with NoUnifier -> main stack clauselist (counter + 1) substitutions 
             variablesinquery answers 
     else raise BackTrack 
with Queue.Empty -> 
    let answers = buildanswer substitutions variablesinquery :: answers in 
    raise BackTrack 

Единственное вычисление, которое происходит на tempstack, что новые цели были вставлены в нее с помощью другой функции (stacknewsubgoals) (Примечание: стек стек очередей).

Я попытался заменить временную стопку во внутреннем стеке try для стека (где выполняется основной рекурсивный вызов). Вместо того, чтобы переходить в бесконечный цикл (потому что тот же самый стек должен быть передан без изменений снова и снова), он заканчивается исключением Not_Found, которое, в свою очередь, генерируется моим исключением Queue.Empty внизу. По сути, так или иначе очередь в нижней части стека становится пустой, когда она должна быть определенно не пустой.

let stacknewsubgoals tempstack unifier newsubgoals = 
let tempq = Stack.pop tempstack in 
    let subbedq = substituteinqueue tempq unifier (Queue.create()) in 
     if (newsubgoals <> []) then 
      (Stack.push subbedq tempstack; 
      Stack.push (Queue.create()) tempstack; 
      initialize (Stack.top tempstack) (substpredicatelist newsubgoals unifier); 
      tempstack) 
     else 
      (Stack.push subbedq tempstack; 
      ignore (Queue.pop (Stack.top tempstack)); 
      tempstack) 

Здесь вы можете ясно видеть, что единственная вещь, которая изменяется этой функцией, - это tempstack. Любая помощь в определении того, почему исходный стек, передаваемый в качестве аргумента в функции, не остается неизменной, будет очень оценена!

+0

Я переформатировал первый блок кода в вашем вопросе, чтобы лучше соответствовать обычным стандартам кодирования ocaml. Мне легче читать (и, возможно, многие другие). Не стесняйтесь откатывать изменения в свою версию, если вам это не нравится. Я также взял на себя смелость устранить лишние парнеры. Надеюсь, вы не возражаете против такой навязчивой модификации вашей первоначальной записи. – didierc

ответ

5

Это много кода для чтения. Главное, что приходит в голову, это то, что вы используете две изменяемые структуры данных, одну внутри другой. Сыворотка вы делаете Stack.copy, он не собирается копировать очереди внутри. Поэтому, если вы изменяете очереди в этой копии, они также будут изменены в оригинале.

Эти проблемы являются именно тем, почему так приятно использовать неизменные структуры данных.

Возможно, это слишком простой ответ, но, возможно, это поможет.

+0

Отлично! Вот и все! Я закончил все, и все работает! Так что спасибо! : D – krandiash

Смежные вопросы