Implementing the map function for a Pony array

191 Views Asked by At

I have been playing with Pony arrays to understand Pony better, and wanted to write the map function for any arrays.

I am talking about something like the standard map function most languages have nowadays for converting elements of collections, as in Clojure:

(map #(+ 1 %) [1 2 3]) ; => [2 3 4]

But I want it to actually modify the given array, not return a new one.

My current attempt so far runs into many errors due to capabilities:

// array is "iso" so I can give it to another actor and change it
let my_array: Array[U64] iso = [1; 2; 3; 4]

// other actor tries to recover arrays as "box" just to call pairs() on it
let a = recover box my_array end // ERROR: can't recover to this capability
for (i, item) in a.pairs() do
  // TODO set item at i to some other mapped value
  try my_array.update(i, fun(item))? end
end

Anyone knows how this can be done

1

There are 1 best solutions below

0
On BEST ANSWER

Alright, took me a while, but I was able to get things working.

Here's my basic understanding of what's going on (please correct me if I'm wrong)!

The first step was to understand that we need to use aliases to change the capabilities of a variable in Pony.

So, in order to make an iso variable useable as a box, one must alias it by basically, consuming it into another variable:

  let a: Array[U64] ref = consume array // array is "iso"
  for (i, item) in a.pairs() do
    try a.update(i, item + n)? end
  end

This works!!

One more problem I had was that I couldn't do much with the resulting Array[U64] ref. Can't pass it to anyone, for example.

So I wrapped the whole thing into a recover block in order to end up with the same array, but as a val (immutable reference to the array) which is more useful as I can send it to other actors:

let result = recover val
  let a: Array[U64] ref = consume array
  for (i, item) in a.pairs() do
    try a.update(i, item + n)? end
  end
  a
end

Now I can send result to anyone!