Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure基于参数的灵活功能设计?_Clojure - Fatal编程技术网

Clojure基于参数的灵活功能设计?

Clojure基于参数的灵活功能设计?,clojure,Clojure,根据提供的关键字参数值的不同,我有不同的函数。对于这个问题,我想知道根据提供的参数类型,函数的行为会略有不同 示例函数,它递增列表中的每个元素: (defn inc-list [& {:keys [list-str list]}] (let [prepared-list (if-not (nil? list) list (clojure.string/split list-str #","))] (map inc prepared-list))) 让一个多重方法代替测试参数

根据提供的关键字参数值的不同,我有不同的函数。对于这个问题,我想知道根据提供的参数类型,函数的行为会略有不同

示例函数,它递增列表中的每个元素:

(defn inc-list [& {:keys [list-str list]}]
  (let [prepared-list (if-not (nil? list) list (clojure.string/split list-str #","))]
    (map inc prepared-list)))
让一个多重方法代替测试参数的类型有意义吗?我以前没有使用过多种方法,不确定何时使用它们。如果这是个好主意,下面的例子有意义吗

例如:

(defn inc-coll [col] (map inc col))
(defmulti inc-list class)
(defmethod inc-list ::collection [col] (inc-col col))
(defmethod inc-list String [list-str] 
  (inc-col 
    (map #(Integer/parseInt %)
         (clojure.string/split list-str #",")))
首先:
(map'inc x)
x
中的每个项目视为关联集合,并查找由键
'inc
索引的值

user> (map 'inc '[{inc 0} {inc 1} {inc 2}])
(0 1 2)
您可能想要
inc

user> (map inc [0 1 2])
(1 2 3)
接下来,我们尝试
inc
一个字符串,字符串/拆分的参数出现了错误,还有一些拼写错误

如果在
上定义了要分派的multi,那么这些方法应该由类参数化,而不是关键字占位符。我更改了multi,以便它可以处理Clojure知道如何将其视为seq的任何内容。此外,作为一种自行车运动,最好使用
类型
,这为区分Clojure代码中
不提供的输入提供了一些区别:

user> (type (with-meta  {:a 0 :b 1} {:type "foo"}))
"foo"
总而言之:

user> (defn inc-coll [col] (map inc col))
#'user/inc-coll
user> (defmulti inc-list type) 
nil
user> (defmethod inc-list String [list-str]
        (inc-coll (map #(Integer/parseInt %) (clojure.string/split list-str #","))))
#<MultiFn clojure.lang.MultiFn@6507d1de>
user> (inc-list "1,10,11")
(2 11 12)
user> (defmethod inc-list clojure.lang.Seqable [col] (inc-coll (seq col)))
#<MultiFn clojure.lang.MultiFn@6507d1de>
user> (inc-list [1 2 3])
(2 3 4)
user>(defn inc coll[col](地图inc col))
#'user/inc coll
用户>(defmulti inc列表类型)
无
用户>(defmethod inc list String[list str]
(inc coll(map#(Integer/parseInt%)(clojure.string/split list str#“,”))
#
用户>(包括列表“1,10,11”)
(2 11 12)
用户>(defmethod inc list clojure.lang.sekable[col](inc coll(seq col)))
#
用户>(包括列表[1 2 3])
(2 3 4)
第一件事:
(map'inc x)
x
中的每个项目视为关联集合,并查找由键
'inc
索引的值

user> (map 'inc '[{inc 0} {inc 1} {inc 2}])
(0 1 2)
您可能想要
inc

user> (map inc [0 1 2])
(1 2 3)
接下来,我们尝试
inc
一个字符串,字符串/拆分的参数出现了错误,还有一些拼写错误

如果在
上定义了要分派的multi,那么这些方法应该由类参数化,而不是关键字占位符。我更改了multi,以便它可以处理Clojure知道如何将其视为seq的任何内容。此外,作为一种自行车运动,最好使用
类型
,这为区分Clojure代码中
不提供的输入提供了一些区别:

user> (type (with-meta  {:a 0 :b 1} {:type "foo"}))
"foo"
总而言之:

user> (defn inc-coll [col] (map inc col))
#'user/inc-coll
user> (defmulti inc-list type) 
nil
user> (defmethod inc-list String [list-str]
        (inc-coll (map #(Integer/parseInt %) (clojure.string/split list-str #","))))
#<MultiFn clojure.lang.MultiFn@6507d1de>
user> (inc-list "1,10,11")
(2 11 12)
user> (defmethod inc-list clojure.lang.Seqable [col] (inc-coll (seq col)))
#<MultiFn clojure.lang.MultiFn@6507d1de>
user> (inc-list [1 2 3])
(2 3 4)
user>(defn inc coll[col](地图inc col))
#'user/inc coll
用户>(defmulti inc列表类型)
无
用户>(defmethod inc list String[list str]
(inc coll(map#(Integer/parseInt%)(clojure.string/split list str#“,”))
#
用户>(包括列表“1,10,11”)
(2 11 12)
用户>(defmethod inc list clojure.lang.sekable[col](inc coll(seq col)))
#
用户>(包括列表[1 2 3])
(2 3 4)

您的第一个示例是一个模糊的应用程序,它使用了一种称为“按类型分派”的技术。这是因为在消息传递样式中,调用者必须将类型传递给您的函数

因为在每种情况下,您只使用一个关键字args,所以您可以将其定义为:

(defn inc-list
  [m l]
  (->> (case m   ;; message dispatch
         :list l
         :list-str (map #(edn/read-string %) (str/split #",")) l)
       (map inc)))
呼叫方无需通过m:

(defn inc-list
  [l]
  (->> (cond (string? l) (map ...)
             :else l)
       (map inc)))
这种技术的主要缺点是在代码库中引入新类型时必须修改操作过程代码

在Clojure中,它通常被多态性结构e。g、 :

可以在任何类型上实现,例如。g

(extend-type clojure.lang.Seqable
   IncableList
   (inc-list [this] (map inc this)))

(extend-type String
   IncableList
   (inc-list [this] (map #(inc ...) this)))
通过将调度机制与操作过程解耦,并提供数据导向编程的可添加性,允许相同的操作,并在消息传递和类型上调度方面提供额外的灵活性。不过,它们的执行速度比协议慢


在您的示例中,目的是基于类型进行调度,因此您不需要使用多方法,协议是合适的技术。

您的第一个示例是一种称为基于类型调度的技术的模糊应用程序。这是因为在消息传递样式中,调用者必须将类型传递给您的函数

因为在每种情况下,您只使用一个关键字args,所以您可以将其定义为:

(defn inc-list
  [m l]
  (->> (case m   ;; message dispatch
         :list l
         :list-str (map #(edn/read-string %) (str/split #",")) l)
       (map inc)))
呼叫方无需通过m:

(defn inc-list
  [l]
  (->> (cond (string? l) (map ...)
             :else l)
       (map inc)))
这种技术的主要缺点是在代码库中引入新类型时必须修改操作过程代码

在Clojure中,它通常被多态性结构e。g、 :

可以在任何类型上实现,例如。g

(extend-type clojure.lang.Seqable
   IncableList
   (inc-list [this] (map inc this)))

(extend-type String
   IncableList
   (inc-list [this] (map #(inc ...) this)))
通过将调度机制与操作过程解耦,并提供数据导向编程的可添加性,允许相同的操作,并在消息传递和类型上调度方面提供额外的灵活性。不过,它们的执行速度比协议慢


在您的示例中,目的是基于类型进行调度,因此您不需要使用多方法,协议是合适的技术。

谢谢,这非常有用。我为你发现的错误编辑了我的帖子,再次感谢。类型元数据不是我考虑的东西,我不熟悉它。还有一件事,使用多重方法对这个应用程序有意义吗?这样做的优点和缺点是什么?谢谢,这是非常有用的。我为你发现的错误编辑了我的帖子,再次感谢。类型元数据不是我考虑的东西,我不熟悉它。还有一件事,使用多重方法对这个应用程序有意义吗?这样做的利弊是什么?