Оцениваются ли значения по умолчанию для необязательных параметров при каждом вызове функции? - PullRequest
1 голос
/ 24 октября 2019

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

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

let x = ref 0;;

let incr x =
  x := !x + 1;
  !x
;;

let test ?(a = incr x) () = a;;

вызов test () приводит к 1, 2, 3, ..., увеличиваясь каждый раз, но вызов test ~a:123 () не увеличивает ссылочный номер.

Кажетсянапример, поведение test () или test ~a () примерно такое же, как

let test ?a () =
  let a =
    match a with
    | None -> incr x
    | Some a -> a
  in
  body_of_test ~a ()
;;

Это правильный способ моделирования? Кроме того, это поведение где-то задокументировано?

1 Ответ

3 голосов
/ 24 октября 2019

Это действительно предполагаемое поведение. См. Документацию (выделено мной):

Функция вида fun ? lab :( pattern = expr0 ) -> expr эквивалентна fun ? lab : ident -> let pattern = match ident with Some ident -> ident | None -> expr0 in expr

, где ident - этосвежая переменная, за исключением того, что она не указана, когда expr0 оценивается .

Хотя оценка вашего приращения работает так, как вы думаете, это крайне нежелательно«скрыть» эффекты в приложении функции. Примечательно, что следующий код может вернуть либо true, либо false без гарантии того, что другая версия компилятора будет иметь такое же поведение.

let test2 ?(a = incr x) ?(b = incr x) () = a < b
if test2 () then ...
...