【问题标题】:Clojure recur with multi-arityClojure 以多参数重复
【发布时间】:2018-03-29 01:18:03
【问题描述】:

我可能有点超前了,在我学习 Clojure 的第一天,我几乎没有接触过函数,但我想我会雄心勃勃地制作一个递归函数来将浮点值转换为三进制。如果我按名称而不是使用 recur 调用函数,它会很好用。我理解问题是我只是recuring 函数的 1-arity 版本,是否有标准方法来处理多arity 函数中的递归?我正在阅读的书似乎没有涵盖它。

(defn float-to-ternary
  ([x k s]
    (def a (int x))
    (def r (- x a))
    (def carry-string (str s (. Integer toString a 3)))
    (cond
      (== r 0) carry-string
      (> k 20) carry-string
      :default (recur (* 3 r) (inc k) carry-string)
    )
  )
  ([x]
    (def a (int x))
    (def r (- x a))
    (def carry-string (str (. Integer toString a 3) "."))
    (cond
      (== r 0) (str (. Integer toString a 3))
      :default (recur (* 3 r) 1 carry-string)
    )
  )
)

【问题讨论】:

  • (. Integer toString a 3) ~= (Integer/toString a 3)

标签: function recursion clojure


【解决方案1】:

如果您想“将recur 转换为不同的arity”,只需显式调用该函数而不是使用recur

(defn float-to-ternary
  ([x k s]
   (def a (int x))
   (def r (- x a))
   (def carry-string (str s (. Integer toString a 3)))
   (cond
     (== r 0) carry-string
     (> k 20) carry-string
     :default (recur (* 3 r) (inc k) carry-string)))   

  ([x]
   (def a (int x))
   (def r (- x a))
   (def carry-string (str (. Integer toString a 3) "."))
   (cond
     (== r 0) (str (. Integer toString a 3))
     :default (float-to-ternary (* 3 r) 1 carry-string))))

这是安全的。当你不使用recur 时,你“花费”了一个堆栈帧,但其余的递归使用recur,所以没关系。


不过,我也有一些强制性的建议:

  • 除非你真的有充分的理由,否则不要在函数内部使用defdef 创建函数返回时不会超出范围的全局变量!

  • 您不需要使用cond

    • 在第一个正文中,您希望为前两个条件返回 carry-string。您可以只设置一个条件,将两者与or 连接起来,这样您就可以简单地使用if

    • 由于第二次使用只有两个结果,if 再次更有意义。

考虑到这一点,您的代码看起来更像:

(defn float-to-ternary
  ([x k s]
   (let [a (int x)
         r (- x a)
         carry-string (str s (. Integer toString a 3))]
     (if (or (> k 20) (== r 0))
      carry-string
      (recur (* 3 r) (inc k) carry-string))))

  ([x]
   (let [a (int x)
         r (- x a)
         carry-string (str (. Integer toString a 3) ".")]
     (if (== r 0)
       (str (. Integer toString a 3))
       (float-to-ternary (* 3 r) 1 carry-string)))))

【讨论】:

    猜你喜欢
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 2021-11-04
    • 1970-01-01
    相关资源
    最近更新 更多