【问题标题】:Clojure: having difficulty applying protocol to 2 types successfullyClojure:难以成功地将协议应用于 2 种类型
【发布时间】:2014-09-30 17:55:23
【问题描述】:

OtherWhat 的更复杂版本(包装)。它做了What 所做的事情,但更多。我小心地定义了 2 个命名空间。

(ns what)

(defprotocol IWhatever
  (whatever [this]))

(deftype What []
  IWhatever
  (whatever [this]
            (str "whatever")))

(whatever (->What))

(ns other (:require what))

(deftype Other []
  what/IWhatever
  (whatever [this]
            (what/whatever (what/->What))))

(whatever (->Other)) ;bad line

错误是:

clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to resolve symbol: whatever in this context, compiling:(C:\...)

为什么最后一个表达式不能解析?好像找不到名字,但是可以看到我在当前命名空间下重新定义了。

这是无意义的代码,但我使用了最简单的问题示例来说明这一点。如果相关,我会在 LightTable 中运行它。

【问题讨论】:

  • 调用协议函数时,需要使用限定符号,即(dict/get man :name),而不是(get man :name)
  • 它不会调用 Dictionary 版本,因为 Dictionary 中的版本没有实现。在 repl 中尝试一下,自己看看。
  • @Mario 我认为您错过了协议的重点。协议定义了一组多态函数。您调用一个协议函数,它根据第一个参数的类型进行调度。如果您必须为每种实现类型调用不同的函数,那将破坏整个目的。
  • 当您在Item 上调用dict/get 时,REPL 中会发生什么?你试过了吗?
  • 调用无法解析,因为extend-type 没有在当前命名空间中定义新函数。它将函数添加到正在扩展的协议的调度表中。

标签: clojure protocols clojurescript lighttable deftype


【解决方案1】:

用定义协议的命名空间来限定最后一行。我一直想尝试在other 命名空间中调用whatever 方法,因为它是在那里定义的。

(what/whatever (->Other))

感谢@soulcheck 和其他所有花时间提供帮助的人。

【讨论】:

    猜你喜欢
    • 2012-05-29
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多