Когда в OCaml создаются физически разные значения?

Я пытаюсь понять, что такое операторы физического равенства (Pervasives.(==) а также Pervasives.(!=)) значит в OCaml.

Руководство по языку говорит, что выражение "" является "константой", а не "выражением":

6.5 Константы

константа::== ... строковый литерал

но я не могу найти никаких слов, указывающих, что константы по отдельности / предварительно оценены или объединены, а REPL указывает, что изменяемые строковые значения (к счастью) не объединяются.

(* a *)  ""          == "";;             (* false *)
(* b *)  "foo"       == "foo";;          (* false *)
(* c *)  ""          == String.copy "";; (* false *)
(* d *)  ()          == ();;             (* true  *)
(* e *)  (42, -42)   == (42, -42);;      (* false *)
(* f *)  ("", 1)     == ("", 1);;        (* false *)
(* g *)  None        == None;;           (* true  *)
(* h *)  (Some None) == (Some None);;    (* false *)

Раздел " 19.3 Представление типов данных OCaml" предполагает, что спецификация языка требует, чтобы bools, ints, char, значение единицы измерения, простые варианты и пустые списки были самоотверженными.

Должна ли реализация вести себя так, как описано выше, чтобы быть соответствующей реализацией OCaml?

Может ли соответствующая реализация OCaml переписать указатель на b указать на a когда a = b (* structurally *) верно, и оба являются значениями неизменяемого типа (или эффективно неизменяемыми значениями, такими как строки / массивы нулевой длины), как это иногда делается для уменьшения числа достижимых младших значений в поколенческом ГХ?

2 ответа

Решение

Когда я читаю спецификацию языка, очень мало гарантий, когда значения различны. Я полагаю, что единственная гарантия находится в документации модуля Pervasives:

На изменяемых типах, таких как ссылки, массивы, строки, записи с изменяемыми полями и объекты с переменными изменяемого экземпляра, e1 == e2 имеет значение true, если и только если физическая модификация e1 также влияет на e2. На не изменяемых типах поведение ( ==) зависит от реализации; однако гарантируется, что e1 == e2 подразумевает сравнение e1 e2 = 0.

Одна из замечательных особенностей FP - это то, что компилятор и среда выполнения могут делать произвольно умные вещи с неизменяемыми значениями. Так что эта гарантия - это все, что вы действительно хотели бы иметь (ИМХО).

В общем, да, среда выполнения или компилятор свободны (опять же, ИМХО), чтобы делиться (а не делиться) неизменяемыми значениями любым способом, который, по его мнению, будет полезен.

Я бы не стал интерпретировать секцию представления как часть спецификации языка. Это просто полезная документация текущей реализации.

Просто замечание: строковые константы объединяются не так, как вы тестируете:

let f () = "foo"
let b = f () == f () (* true *)

Это действительно может привести к ошибкам, если вы измените вывод f () звонок: это повлияет на все дальнейшие звонки. Консенсус в отношении этого поведения заключается в том, что изменяемая строка является исторической ошибкой (необходимо иметь тип изменяемого буфера, отличный от основного типа строки, для которого выбор кодирования и сложность конкатенации должны быть более важными) и что пул, нарушающий семантику, достаточно интересен по производительности можно допустить, что строковые константы не являются мутированными. Если кто-то хочет избежать объединения, нужно просто позвонить String.copy непосредственно на строковую константу.

Другие вопросы по тегам