Zulip Chat Archive

Stream: lean4

Topic: Pattern matching with arrays


Paul Chisholm (Jan 08 2023 at 23:09):

What is the correct way to pattern match with arrays. It is clear when the arrays are of known length, just use #[], #[a], #[a,b] etc in the pattern. What about when the array length is not known. Playing around I ended up with

def reverse (arr : Array α) : Array α :=
  match arr with
  | ⟨[]⟩    => #[]
  | a::as => (reverse as⟩).push a

but it doesn't seem satisfactory pattern matching on the representation of arrays. Could the explicit reference to the underlying list circumvent the efficient implementation of arrays?

James Gallicchio (Jan 08 2023 at 23:20):

I believe that would in fact cause the array to be converted to a list first. You could build some array slice/list view types, but nothing like that has been built yet...

James Gallicchio (Jan 08 2023 at 23:21):

Arrays don't really support any fast modification other than adding/removing at the end

Marc Huisinga (Jan 08 2023 at 23:28):

James Gallicchio said:

Arrays don't really support any fast modification other than adding/removing at the end

Updating any of the elements is O(1) if the reference count of the array is 1

James Gallicchio (Jan 08 2023 at 23:30):

(err, sorry, I mean adding/removing elements anywhere other than at the end)

Paul Chisholm (Jan 08 2023 at 23:36):

Thanks for the response.
Do I understand correctly. In the above function the pattern creates a new list from the non-empty array, then the recursive call creates a new array from the list? So in similar use cases it would be better just using lists directly.

James Gallicchio (Jan 08 2023 at 23:42):

Yep! It is slightly unfortunate that it is so easy to accidentally turn an array into a list and vice versa, since those operations are not cheap.

Marc Huisinga (Jan 08 2023 at 23:43):

Arrays don't really lend themselves well for pattern matching, they're best worked with using the functions in the standard library. For programming purposes, I'd personally write reverse as follows:

def reverse (xs : Array α) : Array α := Id.run do
  let mut xs := xs
  for i in [0:xs.size/2] do
    xs := xs.swap! i (xs.size - i - 1)
  return xs

Last updated: Dec 20 2023 at 11:08 UTC