模式匹配或多态分派是否可用作clojure中的条件结构?

 剡亚军_191 发布于 2023-01-04 10:32

在静态语言中,我可以用多态替换条件.

在像erlang这样的语言中,我可以使用模式匹配而不是if else.

我在clojure中可以使用什么?

2 个回答
  • 模式匹配多态分派都可用.

    两种形式的多态分派是多方法和协议.

    leontalbot给了一个体面的例子多方法可调度基于的论点一些特定的属性具体的实现(可能是类型,但可以用不同的调度功能).换句话说,决定使用多方法的实现对参数执行一个函数并将其与调度表进行比较.

    这是另一个例子:

    ; Declare multimethod:
    (defmulti get-length class)
    
    ; Provide implementations for concrete types:
    (defmethod get-length java.lang.String [str] (.length str))
    (defmethod get-length java.lang.Number [num] (.length (str num)))
    
    ; Call it for String:
    (get-length "Hello") ;=> 5
    
    ; Call it for a Number (works because Long is a subtype of Number):
    (get-length 1234) ;=> 4
    

    我们在这里使用简单的例子来保持简单,但调度功能可能更有趣.再举一个例子,假设我们要根据输入长度选择排序算法:

    (defn choose-impl [in]
      (cond
        (is-sorted? in) :sorted
        (< (count in) 10) :bubble
        :else :quicksort))
    
    (defmulti my-sort choose-impl)
    
    (defmethod my-sort :sorted [in] in)
    
    (defmethod my-sort :bubble [in] (my-bubble-sort in))
    
    (defmethod my-sort :quicksort [in] (my-quicksort in))
    

    这个是设计的,您可能不会以这种方式实现它,但我希望它是使用不同调度函数的好例子.

    协议是一个不同的东西,更像是Java和其他OO语言中已知的接口.您定义一组形成协议的操作,然后提供各种类型的实现.

    ; Protocol specification:
    (defprotocol my-length (get-length [x]))
    
    ; Records can implement protocols:
    (defrecord my-constant-record [value]
      my-length
        (get-length [x] value))
    
    ; We can "extend" existing types to support the protocol too:
    (extend-protocol my-length
      java.lang.String
        (get-length [x] (.length x))
      java.lang.Long
        (get-length [x] (.length (.toString x))))
    
    ; Now calling get-length will find the right implementation for each:
    (get-length (my-constant-record. 15)) ;=> 15
    
    (get-length "123") ;=> 3
    
    (get-length 1234) ;=> 4
    

    最后,模式匹配可用于非常流行的core.match库:

    (doseq [n (range 1 101)]
      (println
        (match [(mod n 3) (mod n 5)]
          [0 0] "FizzBuzz"
          [0 _] "Fizz"
          [_ 0] "Buzz"
          :else n)))
    

    2023-01-04 10:34 回答
  • 你想使用multimethods.这是一篇很好的文章,解释了如何使用它们. http://adambard.com/blog/structured-clojure-protocols-and-multimethods/

    (def speed 24)
    
    (defmulti get-speed :type)
    
    (defmethod get-speed :european       [_] speed)
    (defmethod get-speed :african        [_] (+ speed 2))
    (defmethod get-speed :norwegian-blue [_] (* speed 1.05))
    
    (get-speed {:type :european}) 
    ; => 200
    

    2023-01-04 10:35 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有