Я хотел бы построить функцию, которая, учитывая двумерную матрицу и некоторый элемент из этой матрицы, будет возвращать индексы положения элемента:
(get-indices [[1 2 3] [4 5 6] [7 8 9]] 6)
;=> [1 2]
, который при возврате вернет сам элемент:
(get-in [[1 2 3] [4 5 6] [7 8 9]] [1 2])
;=> 6
Я хотел, чтобы функция (get-index) была быстрой, поэтому я думал о создании макроса, который расширится до чего-то похожего на часть (cond ...)
этой функции (но универсальную для каждой 2D-матрицы размера NxN) :
(defn get-indices
[matrix el]
(let [[[a b c] [d e f] [g h i]] matrix]
(cond
(= a el) [0 0]
(= b el) [0 1]
(= c el) [0 2]
(= d el) [1 0]
(= e el) [1 1]
(= f el) [1 2]
(= g el) [2 0]
(= h el) [2 1]
(= i el) [2 2])))
Я придумал этот макрос:
(defmacro get-indices
[matrix el]
(let [size (count matrix)
flat (flatten matrix)
compare-parts (map #(list '= % el) flat)
indices (for [x (range size) y (range size)] [x y])]
(cons 'cond (interleave compare-parts indices))))
Это выглядело просто замечательно ... Но при вызове с помощью var, а не прямого значения, выдается исключение:
(def my-matrix [[1 2 3] [4 5 6] [7 8 9]])
(get-indices my-matrix 6)
;=> java.lang.UnsupportedOperationException: count not supported on this
; type: Symbol (NO_SOURCE_FILE:0)
Мне кажется, что символ "матрица" не разрешен к значению во время расширения макроса или что-то в этом роде, но я абсолютный новичок в макросах ...
Как я могу заставить этот макрос работать также с переменными в качестве аргументов?
Я также думал об использовании синтаксической кавычки и т. Д., Но я хотел бы избежать использования (let ...)
в качестве части вывода макроса и также не знал, как реализовать (interleave compare-parts indices)
в синтаксической кавычке ....