【问题标题】:Canonical approach to return based on type of the argument in Clojure基于 Clojure 中参数类型的典型返回方法
【发布时间】:2019-08-12 13:18:18
【问题描述】:

如果参数是一个符号,则返回它。如果参数是一个列表,则调用另一个方法。

Clojure 新手,找不到规范的方法。在 Python 中,可以这样做:

def return_on_arg_type(arg):
  if type(arg) is str:
    return arg
  if type(arg) is list:
    return another_method(arg)

也许我可以使用多种方法,但如何匹配参数的类型以及 Clojure 中可接受的类型匹配?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    Clojure 中基本上有 3 种调度方法:

    1. 如 Alan 所述,将 cond 与谓词(即返回 true 或 false 且名称通常以 ? 结尾的方法)结合使用。
    2. 使用根据第一个参数的类型分派的协议。这方面的参考文档位于https://clojure.org/reference/protocols
    3. 多方法。您可以将 Multimethods 视为一种可编程的调度方法。他们可以做的不仅仅是查看参数的类型,他们还可以查看参数,计算向量参数上的元素等等。 https://clojure.org/reference/multimethods 的规范文档

    查看Clojure multimethods vs. protocols,了解有关多方法与协议的简短讨论。

    【讨论】:

      【解决方案2】:

      不确定目标,但这应该可行:

      (defn something [arg]
        (cond
          (str? arg)  arg
          (list? arg) (other-fn arg)))
      

      【讨论】:

      • 有效!问题的另一部分是:是否有更好的方法(更符合语言习惯)来做同样的事情?
      • cond 足够地道。你也可以试试cond->
      • 这完全是惯用的,因为它完全简单明了。非玩具问题可能需要协议或多方法,但这不需要。
      【解决方案3】:

      可以在 Clojure 中检查类型。它不是无类型语言。

      如果您需要一个简单的调度机制,Alan 提出的代码是惯用的恕我直言。 这里还有其他可能性。您已经提到的一个:多方法。 你的例子可以写成

      (defmulti something class [arg])
      (defmethod something String [arg] arg)
      (defmethod something java.util.List [arg] (some-other arg)) 
      

      在这种情况下,调度 fn 是 class,但您可以实现任何类型的调度条件。

      还有clojure.match,一个通用匹配库(等等)。见https://github.com/clojure/core.match

      【讨论】:

        【解决方案4】:

        除了使用多方法或方法来显式检查之外,还可以使用协议对第一个参数的类型进行分派:

        (defprotocol OnArgTypeReturner
          (return-on-arg-type [arg]))
        
        (extend-protocol OnArgTypeReturner
          String
          (return-on-arg-type [arg] arg)
          clojure.lang.IPersistentList
          (return-on-arg-type [arg] "another-method-called"))
        
        (return-on-arg-type "foo")
        ;; => "foo"
        
        (return-on-arg-type '(1 2 3))
        ;; => "another-method-called"
        

        【讨论】:

          猜你喜欢
          • 2022-11-04
          • 2021-11-10
          • 2018-08-10
          • 1970-01-01
          • 2023-03-30
          • 2020-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多