madeinQuant
madeinQuant

Reputation: 1813

Different result in OCaml and ReasonML

There is a case mapping two vectors into a single vector. I expected that the result of both ML should be same. Unfortunately, the result of ReasonML is different. Please help and comment how to fix it.

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]]]

Upvotes: 1

Views: 195

Answers (3)

madeinQuant
madeinQuant

Reputation: 1813

@Igor Kapkov, thank you for your help. Base on your comment, I found a pipeline statement in the link, there is a summary.

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


[11,22,33]

Upvotes: 1

glennsl
glennsl

Reputation: 29106

The result is the same, but you're using different methods of printing them. If instead of Js.log you use rtop or sketch.sh, you'll get the output you expect:

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

Js.log prints it differently because it is a BuckleScript binding to console.log, which will print the JavaScript-representation of the value you give to it. And lists don't exist in JavaScript, only arrays do.

The way BuckleScript represents lists is pretty much the same way it is done natively. A list in OCaml and Reason is a "cons-cell", which is essentially a tuple or a 2-element array, where the first item is the value of that cell and the last item is a pointer to the next cell. The list type is essentially defined like this:

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

And with this definition could have been constructed with:

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

which is represented in JavaScript like this:

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

Lists are defined this way because immutability makes this representation very efficient. Because we can add or remove values without copying all the items of the old list into a new one. To add an item we only need to create one new "cons-cell". Using the JavaScript representation with imagined immutability:

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

And to remove an item from the front we don't have to create anything. We can just get a reference to and re-use a sub-list, because we know it won't change.

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

The downside of lists is that adding and removing items to the end is relatively expensive. But in practice, if you structure your code in a functional way, using recursion, the list will be very natural to work with. And very efficient.

Upvotes: 4

Igor Kapkov
Igor Kapkov

Reputation: 3899

This is the same result. If you run:

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

You'll get:

[11,[22,[33,0]]]

Upvotes: 4

Related Questions