다음 자체 코드는 OCaml의 문제 (코드 생성 가능성이 있음)를 강조 표시합니다. 어레이 x는 [0..9]에있는 노드에 대한 연결 정보를 가지고 있습니다. init_graph 함수는 원래 모든 노드에 대해 들어오는 노드의 명시 적 배열을 구성했습니다. 아래에 표시된 축소 버전은 연결된 두 개의 노드를 인쇄합니다.가능한 OCaml 코드 생성 버그
함수 init_graph2는 "쓸모없는"else 분기를 제외하고는 init_graph와 동일합니다. 그러나이 두 함수에 의해 산출 된 결과는 상당히 다릅니다. 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()
업데이트 : 분명히 잘못이다 "쓸모없는"등의 init_graph2에서 Ocamllint의에 플래그 다른 지점입니다.
둘째로, camlspotter가 제안한 들여 쓰기 방법은이 시나리오에서 오도 될 수 있습니다. Ocamllint의 조언에 따라 else 브랜치를 주석 처리합니다. taureg-mode를 사용하는 Emacs는 명시 적으로 모든 것이 정상이라고 믿도록 지시하지 않는 한이 코드를 다시 들여 쓰지 않습니다.
이러한 상황에서 경고를 발생시키는 보풀 같은 도구가 필요합니다. 나는 이것에 대한 좋은 제안을 기다리고있다.
감사합니다.
작은 부록 : let .. in과 begin .. 행을 교환하면 원하는 그룹이 만들어집니다. – user3240588
설명합니다. 나는 taureg-mode를 사용하고 있지만, 너무 미묘하고 예기치 않기 때문에 들여 쓰기를 놓쳤습니다. ocamllint와 같은 자동 도구가 잠재적 인 문제 발생 지점으로 강조 표시합니까? 내 코드 기반의 여러 위치에 비슷한 코드가 있습니다. 또한, 비슷한 두 가지를 복용 ocaml에 대한 내 다른 질문을 설명 할 수 있습니까? 감사! – user5754881