Как можно распечатать значения OCaml за пределами верхнего уровня? - PullRequest
15 голосов
/ 31 августа 2011

OCaml repl ("toplevel") имеет расширенную печать для любых типов, определенных пользователем или других. Возможно ли получить доступ к этой функциональности за пределами верхнего уровня, вместо того, чтобы писать совершенно собственный набор принтеров значений для своего полного набора типов?

Ответы [ 3 ]

11 голосов
/ 01 сентября 2011

Средство красивой печати является частью библиотеки верхнего уровня.Вы найдете источник в toplevel/genprintval.ml.Это понятно, учитывая, что ему нужна информация о типе: вы не можете просто указать какое-либо значение, выбор pretty-printer зависит от типа.

Если вы хотите использовать этот код в своей программе,вам нужно соединиться с библиотекой верхнего уровня (toplevellib.cma) или скомпилировать в genprintval (что означает, что для анализа типа может быть достаточно битов средства проверки типов, он может стать довольно большим).

В отладчике есть похожая возможность (но я думаю, она не разделяет код) (debugger/printval.ml и debugger/loadprinter.ml).

Существуют сторонние библиотеки, с которыми вы можете напрямую ссылаться, и которые предоставляют довольнополиграфическое оборудование. Extlib s Std.dump обеспечивает очень грубое средство (не основанное на типе). Вывод Джереми Яллопа и Джейка Донхэма - это еще один подход. Этот еженедельный новостной бюллетень Caml предлагает больше предложений.

10 голосов
/ 01 сентября 2011

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

2 голосов
/ 13 июня 2018

Нет. Начиная с OCaml 4.06, компилятор не делает информацию о типе доступной во время выполнения. Поэтому невозможно иметь автономные программы, которые красиво печатают любые данные OCaml без каких-либо компромиссов. Два основных направления:

  1. Некоторая форма предварительной обработки, которая выводит принтеры из определений типов. На сегодняшний день лучшим подходом может быть show plugin для получения ppx . Это требует аннотирования каждого определения типа.
  2. Опираясь только на представление значений во время выполнения. Это не требует усилий со стороны программиста и работает «из коробки» с данными, полученными из внешних библиотек. Однако он не показывает такие вещи, как имена полей записей или любую другую информацию, которая была потеряна во время компиляции. Пример такого подхода подробно описан ниже.

Функция Dum.to_stdout из пакета dum примет любое значение OCaml, включая циклическое, и напечатает их физическое представление в удобочитаемой форме с учетом данных, доступных только во время выполнения.

Простые вещи дают более или менее то, что можно было бы ожидать:

# Dum.to_stdout ("Hello", 42, Some `Thing, [1;2;3]);;
("Hello" 42 (582416334) [ 1 2 3 ])

Циклический & ndash; и общие значения & ndash; показаны с использованием меток и ссылок. Это круговой список:

# let rec cyc = 1 :: 2 :: cyc;;
# Dum.to_stdout cyc;;
#0: (1 (2 #0))

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

# module type Filename = module type of Filename;;
# Dum.to_stdout (module Filename : Filename);;
(
  #0: "."
  ".."
  #1: "/"
  #2: closure (#1 #3: closure ())
  #4: closure ()
  closure (#4)
  closure ()
  closure ()
  closure (#5: closure (#3))
  closure (#5)
  closure (#5)
  closure (closure () #3 #0)
  closure (closure () #3 #0)
  closure (#6: closure (#2 <lazy>) #7: (#8))
  closure (#6 #7)
  closure (#7)
  closure (#7)
  #8: "/tmp"
  closure (closure () "'\\''")
)
...