假设我有三个函数在矩阵上运算:
(defn flip [matrix] (...))
(defn rotate [matrix] (...))
(defn inc-all [matrix] (...))
想象一下,每个函数都需要一个向量向量的向量(其中每个内向量的长度相同)才能正常运行。
我可以提供一个断言矩阵函数来验证矩阵数据的格式是否正确:
(defn assert-matrix [matrix] (...) )
然而,翻转函数(例如)无法知道数据是否已传递给函数已被验证(完全取决于用户是否可以在将其传递给函数之前对其进行验证)。因此,为了保证正确性,需要将翻译定义为:
(defn flip [matrix]
(assert-matrix matrix)
(...))
这里有两个主要问题:
在面向对象语言中,我创建了一个名为Matrix的类,其中包含一个构造函数,用于在创建实例时检查构造函数args的有效性。没有必要重新检查有效性的方法,因为他们可以确信在初始化类时数据已经过验证。
如何在Clojure中实现这一目标?
答案 0 :(得分:2)
有几种方法可以只验证一次数据结构,例如,您可以按照以下方式编写with-matrix
宏:
(defmacro -m> [matrix & forms]
`(do
(assert-matrix ~matrix
(-> ~matrix
~@forms))
允许你这样做:
(-m> matrix flip rotate)
以上扩展了线程宏以更好地处理您的用例。
同一种方法可能存在无限的变化,但这个想法应该仍然是相同的:宏将确保只有在验证成功时才执行一段代码,函数在矩阵上运行而没有任何嵌入的验证代码。而不是每个方法执行一次,每个代码块将执行一次验证。
另一种方法是确保矩阵函数的所有代码路径都在某处具有验证边界。
您可能还想查看trammel
。
答案 1 :(得分:2)
您可以使用协议来表示矩阵上的所有操作,然后创建一个类似于"构造函数的函数"对于矩阵:
(defprotocol IMatrix
(m-flip [_])
(m-rotate [_])
(m-vals [_]))
(defn create-matrix [& rows]
(if (apply distinct? (map count rows))
(throw (Exception. "Voila, what are you doing man"))
(reify
IMatrix
(m-flip [_] (create-matrix rows))
(m-rotate [_] (create-matrix rows))
(m-vals [_] (vec rows)))))
(def m (create-matrix [1 2 3] [4 5 6]))
(m-flip m)