【问题标题】:Multi-method in Clojure not returning expected valueClojure中的多方法不返回预期值
【发布时间】:2014-05-20 10:45:50
【问题描述】:

我正在研究 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 中多态调度的工作原理。我是否因为认为这过于复杂而疯狂?

【问题讨论】:

    标签: inheritance clojure polymorphism dispatch multimethod


    【解决方案1】:

    (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)))

    【讨论】:

    • 感谢您的回答,但两次通话我仍然得到相同的输出。我猜(compile-cmd [::osx "clang"] ...) 中的向量表示以下函数将在这些类型中的每一种上分派,但您能否向我解释一下 juxt 函数发生了什么?
    • 这个改变为我做了。您是否尝试重新加载您的命名空间?
    • 好的,我让它工作了!谢谢。我不得不退出我的 IDE 并重新打开它。重置 repl 连接、保存、关闭和重新打开文件是不够的。有没有更简单的方法来重新加载我的命名空间?
    【解决方案2】:

    juxt 返回一个向量,其中包含对参数的并列函数求值的结果。如果你评估

    ((juxt :os compiler) osx)
    

    你得到

    [:joy.udp/osx "clang"]
    

    这意味着compile-cmd 会在您调用时调度这些值

    (compile-cmd osx)

    因为您的多方法中没有这些调度值,所以您正在触发默认值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-14
      • 1970-01-01
      • 2013-03-22
      • 2012-02-04
      相关资源
      最近更新 更多