Как я могу решить синтаксическую ошибку в цикле в Ocaml? - PullRequest
0 голосов
/ 30 сентября 2019

Я изучаю Ocaml и пытаюсь попрактиковаться в некоторых кодах. В этом случае я хочу создать код, который применяет функцию несколько раз n раз, поэтому она выглядит как f (f (f (.... f (f (x))). Когда n равно 0, это становится тождественной функциейТем не менее, когда я пробую следующий случай, он постоянно говорит, что в последнем коде есть синтаксическая ошибка, подчеркивающая 'done'

let iter : int * (int -> int) -> (int -> int)
= fun (n, f) -> 
match n with
|0 -> x
|_ -> f c in
        for b = n downto 0 do
          let c = iter x
        done;;

Что не так с моим циклом? если это будет работать, когда мой цикл исправлен.

1 Ответ

1 голос
/ 30 сентября 2019

У вас есть несколько ошибок в коде. Во-первых, если вы используете рекурсию, вы должны использовать let rec. Далее, если вы выполняете рекурсию, вам нужно вызвать iter с аргументом, установленным на n-1, и цикл for не нужен. Если вы используете цикл for, нет необходимости рекурсивно вызывать iter.

Кажется, что работает следующее:

let rec iter : int * (int -> int) -> (int -> int) =
fun (n, f) ->
  match n with
  | 0 -> f
  | _ -> fun x -> f ( iter (n-1, f) x )

(* let's use the sqr function as an example *)
let sqr = fun x -> x*x

(* iter(0, sqr) = sqr,  iter(1, sqr) = sqr sqr, iter(2, sqr) = sqr sqr sqr *)
(* So f(2) = sqr(sqr(sqr 2)) = 256 *)

let f = iter (2, sqr)

let _ = print_int ( f 2 )

Также обратите внимание, что функция iter возвращает новый function , поэтому возвращать значение не имеет смысла.

Для полноты вот итерационное решение (не рекомендуется) с использованием цикла for

let rec iter : int * (int -> int) -> (int -> int) =
fun (n, f) ->
  match n with
  | 0 -> f
  | _ -> fun x ->
           let result = ref (f x)   in
           for c = n downto 1 do
             result := f !result
           done;
           !result

Thisверсия изменяет переменную result. result является ссылкой, значение которой читается с использованием !result и записывается с использованием result :=.

Отказ от ответственности: Я не эксперт по ocaml, поэтому вышеприведенное, вероятно, можно улучшить.

...