Clojure 如何以一种高效、干净利落的方式验证函数参数?
假设我有三个作用于矩阵的函数:Clojure 如何以一种高效、干净利落的方式验证函数参数?,clojure,Clojure,假设我有三个作用于矩阵的函数: (defn flip [matrix] (...)) (defn rotate [matrix] (...)) (defn inc-all [matrix] (...)) 假设每个函数都需要一个int向量向量(其中每个内部向量的长度相同)才能正确运行 我可以提供一个断言矩阵函数来验证矩阵数据的格式是否正确: (defn assert-matrix [matrix] (...) ) 但是,flip函数(例如)无法知道传递给函数的数据是否经过验证(在传递给函数之前
(defn flip [matrix] (...))
(defn rotate [matrix] (...))
(defn inc-all [matrix] (...))
假设每个函数都需要一个int向量向量(其中每个内部向量的长度相同)才能正确运行
我可以提供一个断言矩阵函数来验证矩阵数据的格式是否正确:
(defn assert-matrix [matrix] (...) )
但是,flip函数(例如)无法知道传递给函数的数据是否经过验证(在传递给函数之前,用户是否需要验证数据完全取决于用户)。因此,为了保证正确性,flip需要定义为:
(defn flip [matrix]
(assert-matrix matrix)
(...))
这里有两个主要问题:
- 每次调用矩阵函数时都必须不断调用断言矩阵,这是低效的
- 每当我创建一个矩阵函数时,我必须记住调用断言矩阵。我很可能会忘记,因为重复这一点很无聊
在Clojure如何实现这一点 有几种方法可以只验证一次数据结构,例如,您可以使用matrix宏编写一个
,如下所示:
(defmacro -m> [matrix & forms]
`(do
(assert-matrix ~matrix
(-> ~matrix
~@forms))
这将允许您执行以下操作:
(-m> matrix flip rotate)
以上扩展了线程宏,以更好地处理您的用例
同样的方法可能会有无限的变化,但想法应该是一样的:宏将确保只有在验证成功时才执行一段代码,函数在没有任何嵌入验证代码的矩阵上运行。不是每个方法执行一次,而是每个代码块执行一次验证
另一种方法是确保矩阵函数的所有代码路径都有一个验证边界
您可能还想签出。有几种方法可以只验证一次数据结构,例如,您可以使用matrix
宏编写一个,如下所示:
(defmacro -m> [matrix & forms]
`(do
(assert-matrix ~matrix
(-> ~matrix
~@forms))
这将允许您执行以下操作:
(-m> matrix flip rotate)
以上扩展了线程宏,以更好地处理您的用例
同样的方法可能会有无限的变化,但想法应该是一样的:宏将确保只有在验证成功时才执行一段代码,函数在没有任何嵌入验证代码的矩阵上运行。不是每个方法执行一次,而是每个代码块执行一次验证
另一种方法是确保矩阵函数的所有代码路径都有一个验证边界
您可能还想签出。您可以使用协议表示矩阵上的所有操作,然后创建一个函数,其作用类似于矩阵的“构造函数”:
(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)
您可以使用协议来表示矩阵上的所有操作,然后创建一个类似于矩阵“构造函数”的函数:
(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)
如果愿意,实际上可以使用类和Java互操作。看看白炽灯是如何工作的。如果您愿意,实际上可以使用类和Java互操作。看看白炽灯是如何工作的。