Я не уверен на 100%, что понимаю, что делает ваш код (я не знаю Matlab), но это может быть одним из подходов для построения многомерного вектора:
(defn conj-in
"Based on clojure.core/assoc-in, but with vectors instead of maps."
[coll [k & ks] v]
(if ks
(assoc coll k (conj-in (get coll k []) ks v))
(assoc coll k v)))
(defn foo []
(let [w 5, h 4, d 3
indices (for [i (range w)
j (range h)
k (range d)]
[i j k])]
(reduce (fn [acc [i j k :as index]]
(conj-in acc index
;; do real work here
(str i j k)))
[] indices)))
user> (pprint (foo))
[[["000" "001" "002"]
["010" "011" "012"]
["020" "021" "022"]
["030" "031" "032"]]
[["100" "101" "102"]
["110" "111" "112"]
["120" "121" "122"]
["130" "131" "132"]]
[["200" "201" "202"]
["210" "211" "212"]
["220" "221" "222"]
["230" "231" "232"]]
[["300" "301" "302"]
["310" "311" "312"]
["320" "321" "322"]
["330" "331" "332"]]
[["400" "401" "402"]
["410" "411" "412"]
["420" "421" "422"]
["430" "431" "432"]]]
Это работает только в том случае, если indices
идет в правильном порядке (увеличивается), потому что вы не можете conj
или assoc
на векторе где-либо, кроме одного за другим.
Я также думаю, что было бы приемлемо использовать make-array
и построить ваш массив с помощью aset
. Вот почему Clojure предлагает доступ к изменяемым массивам Java; некоторые алгоритмы намного более элегантны, и иногда они нужны вам для производительности. Вы можете всегда выгружать данные в векторы Clojure после того, как закончите, если хотите избежать побочных эффектов.
(я не знаю, какая из этой или другой версии работает лучше.)
(defn bar []
(let [w 5, h 4, d 3
arr (make-array String w h d)]
(doseq [i (range w)
j (range h)
k (range d)]
(aset arr i j k (str i j k)))
(vec (map #(vec (map vec %)) arr)))) ;yikes?