Следующий автономный код указывает на проблему в OCaml, возможно, связанную с генерацией кода. Массив x содержит информацию о связности для узлов в [0..9]. Функция init_graph изначально создавала явные массивы входящих узлов для каждого узла. Уменьшенная версия, показанная ниже, просто печатает два соединенных узла.
Функция init_graph2 идентична init_graph за исключением «бесполезной» ветки else. Но результаты, полученные этими двумя функциями, совершенно разные. Вы можете запустить его и увидеть, что init_graph в некоторых случаях пропускает второй if-then-else!
Мы запускали эту программу на версиях 3.12.1 (с соответствующей заменой make_matrix), 4.03.0 и 4.03.0+flambda. У всех одна и та же проблема.
Я имел дело с этой и связанными с ней проблемами, когда OCaml таинственным образом пропускает ветки или в некоторых случаях берет обе ветки. Благодаря соавтору мы смогли сократить реальный код до небольшого автономного примера.
Любые идеи о том, что здесь происходит? И есть ли способ избежать этой и связанных с ней проблем?
let x =
let arr = Array.make_matrix 10 10 false in
begin
arr.( 6).( 4) <- true;
arr.( 2).( 9) <- true;
end;
arr
let init_graph () =
for i = 0 to 9 do
for j = 0 to (i-1) do
begin
if x.(i).(j) then
let (i_inarr, _) = ([||],[||]) in
begin
Format.printf "updateA: %d %d \n" i j;
end
(* else () *)
;
if x.(j).(i) then
let (j_inarr, _) = ([||],[||]) in
begin
Format.printf "updateB: %d %d \n" i j;
end
end
done
done;
Format.printf "init_graph: num nodes is %i\n" 10
let init_graph2 () =
for i = 0 to 9 do
for j = 0 to (i-1) do
begin
if x.(i).(j) then
let (i_inarr, _) = ([||],[||]) in
begin
Format.printf "updateA: %d %d \n" i j;
end
else ()
;
if x.(j).(i) then
let (j_inarr, _) = ([||],[||]) in
begin
Format.printf "updateB: %d %d \n" i j;
end
end
done
done;
Format.printf "init_graph: num nodes is %i\n" 10
let test1 = init_graph ()
let test2 = init_graph2 ()
Обновление: Ocamllint помечает ветку else в init_graph2 как "бесполезную", что явно неверно.
Во-вторых, именно в этом случае метод отступов, предложенный camlspotter, может ввести в заблуждение. Мы следуем совету Ocamllint и закомментируем ветку else. Emacs с taureg-mode не меняет отступ в этом коде, если его явно не попросить, чтобы мы поверили, что все в порядке.
Что необходимо, так это инструмент, похожий на ворс, который выдает предупреждение в таких ситуациях. Жду хороших предложений по этому поводу.
Спасибо.