Маршал и волшебная копия в js_of_ocaml
Вопрос новичка. Я просматриваю очень хорошую книгу Ocaml ORA. Когда я пошел поиграть с примером magic_copy из раздела Marshal, я был ближе к браузеру, чем к терминалу, поэтому я попробовал его на верхнем уровне ocsigen в браузере, где я был удивлен, получив результат:
(* js_of_ocaml *)
# let ora_magic_copy a =
let s = Marshal.to_string a [Marshal.Closures] in
Marshal.from_string s 0;;
val ora_magic_copy : 'a -> 'b = <fun>
# (ora_magic_copy 2 : float) +. 3.1;;
- : float = 5.1
Проверяя, изменилось ли что-то между ocaml 2 (текущая версия, когда книга была написана) и ocaml 3.12.1, используемой на верхнем уровне, установленном на моей машине, и js_of_ocaml, я попробовал тот же пример на обычном верхнем уровне, установленном на моей машине, и получил результат, объясненный в книге: ошибка из-за проблемы системы типов с проверкой значений Marshaled.
(* Linux toplevel *)
# (ora_magic_copy 3: float) +. 2.1;;
Segmentation fault (core dumped)
Мне просто любопытно: почему?
Я вижу, что в трех случаях Marshal.to_string дает одну и ту же строку: linux, маршаллизирующий int, js_of_ocaml, маршаллинг и int, js_of_ocaml, маршаллизирующий float. Нечетным является то, что linux toplevel управляет флотом.
Это связано с тем, что js_of_ocaml использует базовые типы javascript? Или просто... неопределенное поведение?
1 ответ
Да, ваша проблема связана с тем, что вы тестируете на уровне javascript.
Когда вы используете стандарт ocaml
на высшем уровне +.
Операция работает на поплавках OCaml, то есть в двойном боксе внутри блока, два параметра +.
Ожидается, что указатели на такие коробки. В вашем примере вместо указателя вы даете целое число OCaml 2
(внутренне он представлен как 5, то есть 2 << 1 + 1), поэтому OCaml segfaults при попытке прочитать двойное число, которое должно быть в позиции 0x5 в памяти...
в js_of_ocaml
браузер, числа с плавающей точкой - это просто числа с плавающей точкой в JavaScript, а целые числа - это целые числа из JavaScript, и +.
это дополнение javascript, которое может добавлять целые числа и числа с плавающей точкой (путем автоматического преобразования целых чисел в числа с плавающей точкой), поскольку значения помечены их типами.