Jestem nowy w Ocaml i mam z tym problemkod (poniżej). Próbuję napisać program do sortowania tablicy. Podzieliłem tablicę na dwie połówki, a następnie użyłem Array.sort na tych dwóch tablicach (naprawię to później, więc nie użyję Array.sort). A potem chciałem porównać elementy z tych dwóch tablic, ale mój kod nie działa. Czy ktoś może mi powiedzieć, gdzie jest problem?
let a =[|5;4;2;6;1;3|] ;;
let n = Array.length a;;
let l= Array.sub a 0 (n/2);;
Array.sort compare l;;
l;;
let ll= Array.length l;;
let r= Array.sub a (n/2) (n/2);;
Array.sort compare r;;
r;;
let lr=Array.length r;;
let merge l r a =
let k =ref 0 in
let i = ref 0 in
let j =ref 0 in
while( !i<ll && !j< lr) do
if(l.(!i) <= r.(!j)) then
a.(!k) <- l.(!i)
i:= !i+1
else begin
a.(!k) <- r.(!j)
j:= !j+1;
k:= !k+1
end;
while (!i<ll) do
a.(!k)<-l.(!i)
i:= !i+1;
k:=!k+1;
done;
while (!j<ll) do
a.(!k) <-r.(!j)
j:= !j+1;
k:= !k+1
done;
done;;
merge l r a;;
Odpowiedzi:
1 dla odpowiedzi № 1Twój problem wynika z niezrozumienia instrukcji. Spróbujmy wyjaśnić to w łatwy i krótki sposób:
- Jeśli wyrażenie zwraca wartość, jest to wyrażenie (a
bool
, anint
, afunction
...) - Jeśli nie zwraca wartości (co oznacza efekt uboczny), jest instrukcją (i mówimy, że zwraca
unit
ponieważ tak naprawdę to właśnie robi).
Kiedy masz sekwencję (tak nazywa się wykonywanie wielu instrukcji jeden po drugim), rozdzielasz je za pomocą a ;
.
Na przykład, jeśli to napiszę
let f x = x := 1; print_int !x; print_newline ()
Mam sekwencję i muszę oddzielić moje instrukcje ;
.
Gdybym napisał:
let f x = x := 1 print_int !x print_newline ()
Łatwo zrozumieć, że OCaml nie wie, gdzie instrukcje są oddzielone (jest to x := 1 print_int; !x
? Czy cokolwiek innego?) Dlatego właśnie tego potrzebujesz ;
.
Teraz pojawia się problem if
.
Jeśli piszesz
if cond then instr1; instr2
To, co jest analizowane, jest
(if cond then instr1); instr2
Tak, if cond then instr1
jest instrukcją, ponieważ, cóż, wraca unit
nie? Więc instr2
nie jest w twoim then
blok.
Ale jeśli napiszesz
if cond then let e1 = e2 in instr1; instr2
Następnie instr2
jest w then
blok, ponieważ konstrukcja let ... in
tworzy blok, w którym wszystkie instrukcje są zagnieżdżone.
Jeśli zaczynasz z OCaml, moja cenna rada byłaby następująca: zawsze piszbegin ... end
w twoich warunkach. Zapewnisz, że to, co piszesz, jest tym, o czym myślisz, że jest parsowane.
1 dla odpowiedzi nr 2
Jestem zbyt nowy, by komentować, ale wskażę, że każdy blok potrzebuje albo nawiasów ()
lub begin ... end
. Tak więc, twoja pierwsza if
oświadczenie powinno mieć then begin
na końcu linii. Oświadczenia między begin
i else
potrzebujemy średników, aby je rozdzielić, jak w:
if(l.(!i) <= r.(!j)) then begin
a.(!k) <- l.(!i);
i:= !i+1
end else begin
a.(!k) <- r.(!j);
j := !j+1;
k:= !k+1
end;
Potrzebne są również pierwsze dwie linie pętli whilesemi-colons, ponieważ są one również blokiem instrukcji. Zauważ, że nie potrzebujesz średnika dla ostatniej instrukcji w bloku. Są separatorami, a nie końcem instrukcji. Ponadto, jako skrót, możesz użyć incr i
dla i := !i + 1
i podobne stwierdzenia. Nigdy nie używaj l ani ll jako nazw zmiennych. :-)