【问题标题】:Functional way to check primality of a number in clojure在clojure中检查数字素数的功能方法
【发布时间】:2015-08-09 16:39:55
【问题描述】:

编写以下检查数字是否为素数的代码更正确的功能方法是:

(defn prime? [n]
  (loop [k 2]
    (cond
     (< k n) (if (not= 0 (mod n k))
               (recur (inc k))
               (println n "is not prim"))
     :else (println n "is prim"))))

【问题讨论】:

    标签: clojure functional-programming


    【解决方案1】:

    无论您使用哪种算法来测试素数,“正确的函数方式”都是让您的 prime? 函数返回 truefalse。就目前而言,您的函数返回 nil 并具有副作用(打印出一些东西)。

    然后您可以执行(println (prime? x)) 来检查特定数字,并将副作用限制在该单个语句中。

    【讨论】:

    • 感谢您的解释。我仍然无法理解的是,print 函数已知有副作用,但如果我们为print 提供相同的参数,它将始终给出相同的输出。那么为什么print 是一个副作用函数呢?
    • @teymuri “输出”在纯函数式编程中通常指的是返回值。虽然print 总是返回nil,但它有一个副作用(即它可以观察到除了计算和返回结果之外的其他事情)写入*out*
    【解决方案2】:

    使用every?range等标准库函数的更简单方法:

    (defn divisible? [a b]
      (zero? (mod a b)))
    
    (defn prime? [n]
      (and (> n 1) (not-any? (partial divisible? n) (range 2 n))))
    

    并将 I/O 重构为一个单独的函数以提高重用性:

    (defn format-primality [n]
      (str n " " (if (prime? n) "is prim" "is not prim")))
    
    (def print-primality
      (comp println format-primality))
    

    例子:

    user=> (map (fn [n] [n (prime? n)]) (range 1 15))
    ([1 false] [2 true] [3 true] [4 false] [5 true] [6 false] [7 true]
     [8 false] [9 false] [10 false] [11 true] [12 false] [13 true] [14 false])
    

    【讨论】:

    • 非常好的例子!那么这个版本(只是你的改动)也是一个没有副作用的纯功能版本吗? (defn prime? [n] (if (some #(= 0 (mod n %)) (range 2 n)) "Not prim" "Prim"))
    • @teymuri 该函数对于相同的参数总是给出相同的结果,并且它不会执行任何副作用;所以是的,它是纯净的。仅供参考,在我的示例中,除了 print-primality 之外的所有函数都是纯函数。
    • @elyse 直到n,您才需要检查。 sqrt n 是检查数字是否为素数的最大限制,可以节省大量时间。 stackoverflow.com/q/5811151/2610955
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-12
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 2018-07-07
    • 2014-05-10
    • 1970-01-01
    相关资源
    最近更新 更多