[SBCL] CL-USER>
(defun map-multidimensional-array (function array)
  "Map `function` over the contents and indices of `array`.

  For each element of `array`, `function` will be called with that element and
  its indices, and so `function` must accept `(1+ (array-rank a))` arguments.

  `array` can be any number of dimensions.

  "
  ;; We keep a few extra data structures around to efficiently compute
  ;; everything we need:
  ;;
  ;; BOUNDS: a vector of the array bounds.
  ;; INDICES: a list of the indices of the current element, to apply FUNCTION over.
  ;; INDICES%: a vector of the cons cells of indices, so we can efficiently
  ;;           read/write indices in the middle of the list.
  (let* ((bounds (coerce (array-dimensions array) 'vector))
         (indices (make-list (array-rank array) :initial-element 0))
         (indices% (coerce (maplist 'identity indices) 'vector))
         (last (1- (array-rank array))))
    (macrolet ((iref (index)
                 `(car (aref indices% ,index))))
      (labels
          ((bound (index)
             (aref bounds index))
           (increment-indices (&optional (index last))
             ;; After each iteration we increment the last (low-order) index.
             ;; If that pushes it over the bound we'll reset it to zero and
             ;; "carry" the increment over to the next index.  We're done when
             ;; we overflow and fall off the left end of the index array.
             (unless (minusp index)
               (when (= (incf (iref index))
                        (bound index))
                 (setf (iref index) 0)
                 (increment-indices (1- index))))))
        (loop
          :for i :from 0 :below (array-total-size array)
          :do (progn
                (apply function (row-major-aref array i) indices)
                (increment-indices)))))))

MAP-MULTIDIMENSIONAL-ARRAY

[SBCL] CL-USER>
(defun test (arr)
  (flet ((work (value &rest indices)
           (format t "~A / ~A / ~S~%" value (apply #'aref arr indices) indices)))
    (map-multidimensional-array #'work arr)))

TEST

[SBCL] CL-USER> (test "hello")
h / h / (0)
e / e / (1)
l / l / (2)
l / l / (3)
o / o / (4)
NIL

[SBCL] CL-USER> (test "x")
x / x / (0)
NIL

[SBCL] CL-USER> (test "")

NIL

[SBCL] CL-USER> (test #2a((a b c) (d e f)))
A / A / (0 0)
B / B / (0 1)
C / C / (0 2)
D / D / (1 0)
E / E / (1 1)
F / F / (1 2)
NIL

[SBCL] CL-USER>
(test #4A((((:start 1 2 3)
           (4 5 6 7)
           (8 9 10 11))
          ((12 13 14 15)
           (16 17 18 19)
           (20 21 22 23)))
         (((1000 1001 1002 1003)
           (1004 1005 1006 1007)
           (1008 1009 10010 10011))
          ((10012 10013 10014 10015)
           (10016 10017 10018 10019)
           (10020 10021 10022 10023)))))
START / START / (0 0 0 0)
1 / 1 / (0 0 0 1)
2 / 2 / (0 0 0 2)
3 / 3 / (0 0 0 3)
4 / 4 / (0 0 1 0)
5 / 5 / (0 0 1 1)
6 / 6 / (0 0 1 2)
7 / 7 / (0 0 1 3)
8 / 8 / (0 0 2 0)
9 / 9 / (0 0 2 1)
10 / 10 / (0 0 2 2)
11 / 11 / (0 0 2 3)
12 / 12 / (0 1 0 0)
13 / 13 / (0 1 0 1)
14 / 14 / (0 1 0 2)
15 / 15 / (0 1 0 3)
16 / 16 / (0 1 1 0)
17 / 17 / (0 1 1 1)
18 / 18 / (0 1 1 2)
19 / 19 / (0 1 1 3)
20 / 20 / (0 1 2 0)
21 / 21 / (0 1 2 1)
22 / 22 / (0 1 2 2)
23 / 23 / (0 1 2 3)
1000 / 1000 / (1 0 0 0)
1001 / 1001 / (1 0 0 1)
1002 / 1002 / (1 0 0 2)
1003 / 1003 / (1 0 0 3)
1004 / 1004 / (1 0 1 0)
1005 / 1005 / (1 0 1 1)
1006 / 1006 / (1 0 1 2)
1007 / 1007 / (1 0 1 3)
1008 / 1008 / (1 0 2 0)
1009 / 1009 / (1 0 2 1)
10010 / 10010 / (1 0 2 2)
10011 / 10011 / (1 0 2 3)
10012 / 10012 / (1 1 0 0)
10013 / 10013 / (1 1 0 1)
10014 / 10014 / (1 1 0 2)
10015 / 10015 / (1 1 0 3)
10016 / 10016 / (1 1 1 0)
10017 / 10017 / (1 1 1 1)
10018 / 10018 / (1 1 1 2)
10019 / 10019 / (1 1 1 3)
10020 / 10020 / (1 1 2 0)
10021 / 10021 / (1 1 2 1)
10022 / 10022 / (1 1 2 2)
10023 / 10023 / (1 1 2 3)
NIL

[SBCL] CL-USER> (test #0acool)
COOL / COOL / NIL
NIL