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)
    (...))
这里有两个主要问题:

  • 每次调用矩阵函数时都必须不断调用断言矩阵,这是低效的
  • 每当我创建一个矩阵函数时,我必须记住调用断言矩阵。我很可能会忘记,因为重复这一点很无聊
在面向对象语言中,我将创建一个名为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互操作。看看白炽灯是如何工作的。