用于向具有各种数据字段的用户申请的功能

问题描述 投票:0回答:4

问题出现在我练习an Observer topic in a tutorial时我试图将该功能应用于用户但不能使用用户的数据字段,如姓名,姓氏。

假设用户可能有不同数量的数据字段,因此我们必须使用& args参数。我的代码不起作用:

(ns observer.core)
(def user {:name "Alan" :surname "Smith" :alias "Mike"})
(def user2 {:name "Jane" :surname "Smith"})
(apply
 (fn [& args] (println (str "I am " (:name args) " " (:surname args) ".")))
   user)
(apply
 (fn [& args] (println (str "My sister is " (:name args) " " (:surname args) ".")))
   user2)

输出:

I am  .
My sister is  .
observer.core> 

如何修复它必须使用apply函数?

clojure parameter-passing
4个回答
2
投票

apply将地图转换为seq,即{:name "Alan" :surname "Smith" :alias "Mike"}变为([:name "Alan"] [:surname "Smith"] [:alias "Mike"])

您可以将其放回地图中,如果这是您需要的:

(let [user {:name "Alan" :surname "Smith" :alias "Mike"}]
    (apply
        (fn [& args]
            (let [args (into {} args)]
                (println (str "I am " (:name args) " " (:surname args) "."))))
        user))

但对我来说这看起来有点紧张。我相信如果我知道如何使用这个功能,解决方案可能会更好。

通常有两种类型的函数:(fn :text "some" :row 25)(fn {:text "some" :row 25})


1
投票

本着学习的精神:

看看Clojure - Cheatsheet。与Clojure合作10年,我仍然每天使用它。

(apply some-func (list x y z))成为(some-func x y z),因为apply假设第二个参数是一个列表(然后它解包)。

而您目前正在做的是将所有参数收集回名为args的列表中

(def user {:name "Alan" :surname "Smith" :alias "Mike"})
(apply
  (fn [& args]
    (prn 'ARGS args)  ;; lets see what is actually in args
    (println (str "I am " (:name args) " " (:surname args) ".")))
  user)
;; -> ARGS ([:name "Alan"] [:surname "Smith"] [:alias "Mike"])
;; -> I am  .

输出就像@akond所说的那样。

当然,您可以将'用户'放在向量(或列表)中,但是不要使用'&'将所有内容收集回列表中(然后您必须再次选择内容):

(def user {:name "Alan" :surname "Smith" :alias "Mike"})
(apply
  (fn [args]
    (prn 'ARGS args) 
    (println (str "I am " (:name args) " " (:surname args) ".")))
  [user])

那会给你你想要的输出。但这或许有点奇怪,但如果你必须使用apply并且你可以控制参数的“列表”部分,那肯定是可行的。

所以,@ akond的解决方案简单而干净。 并用Clojure "destructing"增加它:

(def user {:name "Alan" :surname "Smith" :alias "Mike"})
(apply
  (fn [& args]
    (let [{:keys [name surname alias]} (into {} args)]
      (println (str "I am " name " " surname "." (when alias (str " But call me " alias "!"))))))
  user)

0
投票

我相信你打算做这样的事情:

(def user  {:name "Alan" :surname "Smith" :alias "Mike"})
(def user2 {:name "Jane" :surname "Smith"})

(defn fn-1
  [item]
   (println (str "I am " (:name item) " " (:surname item) ".")) )
(defn fn-2
  [item]
  (println (str "My sister is " (:name item) " " (:surname item) ".")))

  (fn-1 user)
  (fn-2 user2)

结果:

I am Alan Smith.
My sister is Jane Smith.

0
投票

必须通过列表包装用户对象或地图。

(ns observer.core)
(defrecord Person [name balance])
(def user (Person. "Alan" 150.34))
(def user2 {:name "Adam" :balance 629.74})
(def observers (atom #{}))
(swap! observers conj (fn [l] (println (str "2. " (:name l)))))
(swap! observers conj (fn [l] (println (str "1. " (:balance l)))))
(println "user")
(vec (map #(apply % (list user)) @observers))
(println "\nuser2")
(vec (map #(apply % (list user2)) @observers))

产量

user
1. 150.34
2. Alan

user2
1. 629.74
2. Adam
observer.core>
© www.soinside.com 2019 - 2024. All rights reserved.