OCaml оценка выражения, порядок? - PullRequest
0 голосов
/ 05 июля 2018

add - это функция, встроенная в OCaml.

Exp:

# add 5 1;;
- : int = 6

Мой вопрос: каков порядок оценки для add 3 (add 5 3)?

# add 3 (add 5 3);;
- : int = 11

Оценивается ли (add 5 3) сначала до 8, затем add 3 (8) оценивается до 11? Или add 3 вычисляется сначала в функцию, а затем (add 5 3) используется в качестве параметра для функции (add 3)?

Спасибо.

Ответы [ 3 ]

0 голосов
/ 05 июля 2018

Просто чтобы завершить ответ Джеффри, вот версия add, которая дает вам знать, когда она выполняется:

# let add a b =
    Printf.printf "Adding %d and %d...\n" a b;
    a + b;;

val add : int -> int -> int = <fun>

Давайте посмотрим на это в действии.

# add (add 1 2) (add 5 8);;

Adding 5 and 8...
Adding 1 and 2...
Adding 3 and 13...

- : int = 16

Итак, здесь сначала оценивается второй add, но вы не можете рассчитывать на него, поскольку он не указан.

Вот тот же пример использования локального let для форсирования порядка:

# let x = add 1 2 in
  add x (add 5 8);;

Adding 1 and 2...
Adding 5 and 8...
Adding 3 and 13...

- : int = 16

А теперь с помощью частичного применения.

# let add_3 = add 3 in
  add_3 (add 5 8);;

Adding 5 and 8...
Adding 3 and 13...

- : int = 16

Конечно, при (чистом) функциональном программировании порядок выполнения не имеет значения, поскольку все является неизменным. Но OCaml не является чисто функциональным, так что эти маленькие хитрости полезно знать. :)

0 голосов
/ 05 июля 2018

Порядок вычисления аргументов в OCaml не указан, то есть он может меняться от одного компилятора к другому.

Давайте создадим функцию, которая оценивается в два этапа:

let mul a =
  Printf.printf "got a: %i\n%!" a;
  fun b ->
    Printf.printf "got b: %i\n%!" b;
    a * b

Выполнение этого с utop (или ocaml) показывает оценку справа налево:

# mul (mul 2 3) (mul 5 7);;
got a: 5
got b: 7
got a: 2
got b: 3
got a: 6
got b: 35
- : int = 210

A let - in может быть введен для форсирования порядка вычисления, что приводит к другой последовательности printfs:

# let mul6 = mul (mul 2 3) in mul6 (mul 5 7);;
got a: 2
got b: 3
got a: 6
got a: 5
got b: 7
got b: 35
- : int = 210
0 голосов
/ 05 июля 2018

Для чего бы то ни было, в OCaml нет встроенной функции add. (Т.е. в модуле Pervasives такого символа нет.)

$ ocaml
        OCaml version 4.06.0

# add;;
Error: Unbound value add

Порядок оценки функции и ее аргументов в OCaml не указан. Таким образом, нет гарантированного заказа.

Это задокументировано в Разделе 7.7.1 руководства OCaml .

Если вы хотите, чтобы оценка происходила в определенном порядке, вы можете использовать let для оценки каждого подвыражения:

# let add a b = a + b;;
val add : int -> int -> int = <fun>
# let temp = add 5 3 in
  add 3 temp;;
- : int = 11
# let tempf = add 3 in
  tempf (add 5 3);;
- : int = 11
...