pythonarraysschemeracket

racket: O(1) array indexing like python's numpy?


I'm using arrays of picture (2-D array) and model (3-D array) data in python for an application where I'm modeling the human body in 3 dimensions. I would like to rewrite the code in Lisp, specifically Racket,

but I'm wondering how succinct expressions in numpy indexing, ie. arr[2][3] will be expressed in Lisp. I could write a recursive function that expands to (car (car ... (car list)))) or (cdr (cdr ... (cdr list)))), but this seems inefficient. Is there a way to get O(1) access time in a Lisp list, vector, or array?

ie.

arr[1,2] = 1

should be done in racket how?


Solution

  • The whole point of using Arrays instead of (linked) lists is that you can random-access index them in constant time. But Racket Arrays provide a lot more than that, including Python-ish slicing, and NumPy-ish array-wide operations. The syntax isn't quite as concise or (at least in my opinion) as nice as in Python, but the ideas are the same.

    You really need to read the whole chapter to understand the best way to write your code, or you're going to end up doing the same kind of thing as if you wrote Python code that used NumPy but then looped over range(len(arr)) all the time.

    But to answer your direct question, the Python/NumPy expression:

    arr[2, 3]
    

    … is written in Racket as:

    (array-ref arr #(2 3))
    

    The Python expression:

    arr[2][3]
    

    … is written as two nested array-ref calls. But then if arr is an actual 2D array (e.g., from NumPy), you shouldn't have been writing it as two indexing expressions in Python any more than you should in Racket, so the fact that it's more verbose isn't really a bad thing.

    Either way, it has the same constant-time lookup.