Разные результаты в OCaml и ReasonML - PullRequest
0 голосов
/ 06 марта 2020

Существует случай, отображающий два вектора в один вектор. Я ожидал, что результат обоих ML должен быть одинаковым. К сожалению, результат ReasonML отличается. Пожалуйста, помогите и прокомментируйте, как это исправить.

OCaml

List.map2 (fun x y -> x+y) [1;2;3] [10;20;30];;
[11;;22;;33]

ReasonML

Js.log(List.map2 ( (fun (x,y) => x+y), [1,2,3], [10,20,30]))
[11,[22,[33,0]]]

Ответы [ 3 ]

3 голосов
/ 06 марта 2020

Результат равен , но вы используете разные способы их печати. Если вместо Js.log вы используете rtop или эскиз. sh, вы получите ожидаемый результат:

- : list(int) = [11, 22, 33]

Js.log печатает его по-другому, потому что это привязка BuckleScript к console.log, которая будет печатать JavaScript -представление значения, которое вы ему дадите. И списки не существуют в JavaScript, только в массивах.

BuckleScript представляет списки почти так же, как это делается изначально. Список в OCaml и Reason - это «cons-ячейка», которая по сути является кортежем или двухэлементным массивом, где первый элемент - это значение этой ячейки, а последний элемент - указатель на следующую ячейку. Тип list по существу определяется так:

type list('a) =
  | Node('a, list('a))
  | Empty;

И с этим определением можно было бы построить с помощью:

Node(11, Node(22, Node(33, Empty)))

, который представлен в JavaScript следующим образом:

[11,[22,[33,0]]]
 ^   ^   ^  ^
 |   |   |  The Empty list
 |   |   Third value
 |   Second value
 First value

Списки определяются таким образом, потому что неизменность делает это представление очень эффективным. Потому что мы можем добавлять или удалять значения, не копируя все элементы старого списка в новый. Чтобы добавить элемент, нам нужно создать только одну новую "cons-ячейку". Используя представление JavaScript с воображаемой неизменностью:

const old = [11,[22,[33,0]]];
const new = [99, old];

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

const old = [11,[22,[33,0]]];
const new = old[1];

Недостатком списков является то, что добавление и удаление элементов до конца относительно дорого. Но на практике, если вы структурируете свой код функционально, используя рекурсию, список будет очень естественным для работы. И очень эффективно.

3 голосов
/ 06 марта 2020

Это тот же результат. Если вы запустите:

Js.log([11,22,33]);

Вы получите:

[11,[22,[33,0]]]
0 голосов
/ 06 марта 2020

@ Игорь Капков, спасибо за помощь. Основываясь на вашем комментарии, я нашел конвейерный оператор в ссылке , там есть сводка.

let a = List.map2 ( (fun (x,y) => x+y), [1,2,3], [10,20,30] )
let logl = l => l |> Array.of_list |> Js.log;
Js.log(logl (a))


[11,22,33]
...