问题描述
我可能会超越自我,在学习Clojure的第一天我几乎没有投入函数的使用,但是我认为我会很有野心,并且会做一个递归函数来将浮点值转换为三进制.如果我通过名称而不是使用 recur
来调用函数,则效果很好.我知道问题在于我只是对该函数的1-arity版本进行 recur
,是否存在处理多arar函数中的递归的标准方法?我正在阅读的书似乎没有涵盖这本书.
I'm probably getting ahead of myself, I'm barely into functions on my first day of learning Clojure, but I thought I would be ambitious and make a recursive function to convert floating values to ternary. If I call the function by name instead of using recur
it works great. I understand the problem is that I am just recur
ing the 1-arity version of the function, is there a standard way to handle recursion in multi-arity functions? The book I'm reading doesn't seem to cover it.
(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)
)
)
)
推荐答案
如果您想" recur
放入另一个Arity",只需显式调用该函数即可,而不是使用 recur 代码>:
If you want to "recur
into a different arity", just explicitly call the function instead of using 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
,所以很好.
This is safe. You "spend" one stack frame when you don't use recur
, but the rest of the recursions use recur
, so it's fine.
我也有一些强制性建议:
I have some obligatory suggestions too though:
- 除非您确实有充分的理由,否则请不要在函数内部使用
-
def .
def
创建的全局变量在函数返回时不会超出范围!
Don't use
def
inside of functions unless you really have a good reason.def
creates global variables that don't go out of scope when the function returns!
您无需使用 cond
.
-
在第一个正文中,您要为前两个条件返回
carry-string
.您可以只创建一个条件,将两个条件与或关联,从而可以简单地使用
if
.
In the first body, you want to return
carry-string
for the first two conditions. You could just make that one condition, connecting the two with anor
, which lets you simply useif
.
由于第二次使用只有两个结果,因此 if
再次有意义.
Since the second use only has two outcomes, if
again makes more sense.
考虑到这一点,您的代码将更像:
Taking this into consideration, your code would look more like:
(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)))))
这篇关于Clojure会反复出现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!