Слово готово дает мне синтаксическую ошибку ocaml? - PullRequest
0 голосов
/ 08 октября 2019

я пытаюсь сделать цикл do done в ocaml, но у меня ошибка синтаксиса в строке 21 (строка, которая только что говорит done), и я не знаю, в чем ошибка.

let ver = 1 in
while ver > 0  do 
let () = Printf.printf "Olá, insere o número de casas que o tabuleiro tem numa linha, separe por um espaço\n" in
let tudo = read_line () in (* Le a linha inserida*)
let ncc = tudo.[0] in (*ncc = Numero de Casas Char*)
let ncs = Char.escaped ncc in (*ncs = Numero de Casas String*)
let nc = int_of_string ncs in (* passa a string para int para termos o numero de casas em int para podermos trabalhar*)
let () = Printf.printf "%d" nc in
let pcc = tudo.[2] in
let pcs = Char.escaped pcc in
let pc = int_of_string pcs in
let () = Printf.printf "%d" pc in
let a1c = tudo.[4] in
let a1s = Char.escaped a1c in
let a1 = int_of_string a1s in
let () = Printf.printf "%d" a1 in
let b1c = tudo.[6] in
let b1s = Char.escaped b1c in
let b1 = int_of_string b1s in
let ver = if (nc < 51 && nc > 0 && pc < 9 && pc > 0  ) then 0 else  1 in
done

Ответы [ 2 ]

2 голосов
/ 08 октября 2019

Ваша последняя строка перед done вычисляет значение для ver, но затем ничего с этим не делает. Выражение не имеет смысла заканчиваться на in.

Возможно, вы пропускаете выражение после in. Иначе не понятно, почему вы рассчитываете ver.

1 голос
/ 08 октября 2019

Проблема с вашим кодом в основном связана с вашим пониманием того, что делает let ... in.

Когда вы набираете let x = ... in expr, вы создаете новую переменную x, которая будет применятьсяв вашем выражении expr и только там. Это означает, что ваши два объявления ver:

let ver = 1 in
...
let ver = if (nc < 51 && nc > 0 && pc < 9 && pc > 0  ) then 0 else  1 in

Они объявляют две разные переменные ver, и только условие используется в условии вашего цикла while (который будет бесконечным циклом). в результате).

Теперь к вашей синтаксической ошибке.

Как указал Джеффри, done указывает на конец цикла. Это не выражение, а скорее закрывающие скобки. Однако let ... in ожидает, что за ним последует выражение (где ваша переменная будет «существовать»). Это не то, что вам нужно, поскольку вы хотите, чтобы новое значение ver выходило за пределы его области действия.

Быстрое и грязное решение

Вы можете объявить ver ссылкой. Это значение, которое вы можете изменить в OCaml (по умолчанию все объявленные значения являются константами). Вы объявляете новую ссылку с ref, назначаете ее с := и читаете ее с !. Пример:

let ver = ref true in (* I switched to a boolean, you can easily go back to integer *)
while !ver do
 (* ... *)
 let b1 = int_of_string b1s in
 ver := not (nc < 51 && nc > 0 && pc < 9 && pc > 0  )
done

Обратите внимание, что это не то, как разработчик OCaml обычно кодирует это, так как мы предпочитаем, чтобы наши переменные оставались неизменными и зацикливались, используя рекурсивную функцию.

Способ OCaml

Рекурсивные функции позволяют делать то, что делает любой цикл while, в то же время давая вам синтаксический контроль над тем, что является изменяемым или нет.

let rec loop () =
 (* ... *)
 let b1 = int_of_string b1s in
 if (nc < 51 && nc > 0 && pc < 9 && pc > 0  ) then () else loop ()
in loop ()

Обратите внимание, что ver нетпеременная здесь, так как цикл напрямую вызывает себя, когда это необходимо. Если вы пытаетесь что-то вычислить, вы можете легко вернуть результат в предложении then. Обратите внимание, что в моих кодах (и в вашем) ни одна переменная не выходит из цикла по умолчанию.

...