我正在研究 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"
*关于助手的注意事项:newget
是根据 ns-qualified 关键字重新定义的::prototype
,它正在使用 in beget
,这基本上只是-assoc
使用该关键字的映射和另一个映射作为其值到馈入它的映射作为论据。clone
这个新的 {:keyword {map-as-val}} 对最终通过底部定义的函数关联到 osx 数据映射中。新定义的数据映射是上面代码底部多方法调用的参数。
我是多方法的新手,只想直观地了解多态调度在 Clojure 中的工作原理。我是否因为认为这过于复杂而疯狂?