Clojure中的多方法没有返回预期值

时间:2014-05-20 10:45:51

标签: inheritance clojure polymorphism dispatch multimethod

我正在阅读Clojure的欢乐书,现在正处于多方法部分。在那本书中,他们给出了一个应该返回一个东西的例子,但是为我返回另一个东西(我已经尝试了LightTable和Emacs)。代码有点长;我尽可能地削减它,但为此道歉。它是倒数第二个命令,没有按预期返回(显示为内联)。我怎样才能正确地完成这项工作?

辅助函数非常偶然,因此您可以先跳到多方法。我把它们包括在内以防它们成为问题的可能来源。如果你需要了解更多,我会在最后添加一个说明来解释它们。

(ns joy.udp
  (:refer-clojure :exclude [get]))

;; helpers
(defn beget [this proto]
  (assoc this ::prototype proto))

(def clone (partial beget {}))

(defn get [m k]
  (when m
    (if-let [[_ v] (find m k)]
      v
      (recur (::prototype m) k))))

;;;;;;; compiler
(defmulti compiler :os)
(defmethod compiler ::unix [m] (get m :c-compiler))
(defmethod compiler ::osx [m] (get m :llvm-compiler))

;;;;;;; home
(defmulti home :os)
(defmethod home ::unix [m] (get m :home))
(defmethod home ::bsd [m] "/home")

;;;;;;; compile-cmd
(defmulti compile-cmd (juxt :os compiler))
(defmethod compile-cmd [:osx "gcc"] [m] (str "/usr/bin/" (get m :c-compiler)))
(defmethod compile-cmd :default [m] (str "Unsure where to locate " (get m :c-compiler)))


;;;;;;;;; hierarchy inheritence
(derive ::osx ::unix)
(derive ::osx ::bsd)
(prefer-method home ::unix ::bsd)
(derive (make-hierarchy) ::osx ::unix)

;;;;;;;;;;;; data-maps
(def unix {:os ::unix, :c-compiler "cc", :home "/home", :dev "/dev"})

(def osx (-> (clone unix)
             (assoc :os ::osx)
             (assoc :llvm-compiler "clang")
             (assoc :home "/Users")))

(compile-cmd osx)  ;; This should return "/usr/bin/gcc"
;=> "Unsure where to locate cc"

(compile-cmd unix)
;=> "Unsure where to locate cc"

*关于帮助者的注意事项:新的get是根据ns限定关键字::prototype重新定义的,该关键字在beget中使用,基本上只是assoc - 使用该关键字的地图和另一个地图作为其作为参数输入的地图的值。这个新的{:keyword {map-as-val}}对最终通过底部定义的clone函数与osx数据映射关联。新定义的数据映射用作上面代码底部的多方法调用的参数。

我是多方法的新手,只想直观地了解多态调度在Clojure中的工作原理。我是否因为认为过于复杂而疯狂?

2 个答案:

答案 0 :(得分:2)

(defmethod compile-cmd [::osx "gcc"] [m] (str "/usr/bin/" (get m :c-compiler)))

应该是

(defmethod compile-cmd [::osx "clang"] [m] (str "/usr/bin/" (get m :c-compiler)))

答案 1 :(得分:1)

juxt返回一个向量,其结果是评估参数上的并置函数。如果您评估

((juxt :os compiler) osx)

你得到了

[:joy.udp/osx "clang"]

这意味着compile-cmd会在您调用

时调度这些值

(compile-cmd osx)

由于您在多方法中没有这些调度值,因此您将触发默认值。