我已经解决了4clojure.com上的45个问题,并注意到在使用递归和累加器解决某些问题时,我尝试解决的一种重复性问题。
我会尽力解释我正在做什么,以便最终得到丑陋的解决方案,希望一些Clojurers能够“理解”我没有理解的东西。
例如,问题34要求编写一个函数(不使用range),将两个整数作为参数并创建一个范围(不使用range)。简单地说,您可以执行(... 1 7),然后获得(1 2 3 4 5 6)。
现在,这个问题不是关于解决这个特定问题的。
如果我想使用递归和累加器来解决这个问题,该怎么办?
我的思考过程如下:
我需要编写一个带有两个参数的函数,我从 (fn [x y] ) 开始。
我需要递归,并且需要跟踪一个列表,我将使用累加器,因此我在第一个函数内部编写了第二个函数,它需要一个额外的参数:
(fn [x y]
((fn g [x y acc] ...) x y '())
(显然我无法在SO上正确格式化Clojure代码!?)
在这里,我已经不确定我是否正确地执行了它:第一个函数必须恰好接受两个整数参数(不是我的调用),我不确定:如果我想使用累加器,我能否在不创建嵌套函数的情况下使用累加器?
然后我想要conj,但我不能这样做:
(conj 0 1)
所以我会做一些奇怪的事情来确保我首先得到一个序列,最终得到这个:
(fn
[x y]
((fn g [x y acc] (if (= x y) y (conj (conj acc (g (inc x) y acc)) x)))
x
y
'()))
但是这会产生这个:
(1 (2 (3 4)))
不要这样写:
(1 2 3 4)
所以我最后加了一个flatten,它能工作但是非常丑陋。
我开始理解一些东西,甚至在某些情况下开始以更Clojuresque的方式“思考”,但我在编写解决方案时遇到了问题。
例如,在这里我决定:
- 使用累加器
- 通过增加x直到达到y来递归
但最终我得到了上面的丑陋代码。
有很多种方法可以解决这个问题,再次强调,并不是我要解决的问题。
我所追求的是,在决定使用cons/conj、使用累加器和递归之后,如何得出这个结果(不是我写的):
#(loop [i %1
acc nil]
(if (<= %2 i)
(reverse acc)
(recur (inc i) (cons i acc))))
不要这样写:
((fn
f
[x y]
(flatten
((fn
g
[x y acc]
(if (= x y) acc (conj (conj acc (g (inc x) y acc)) x)))
x
y
'())))
1
4)
我知道解决一些问题是一个开始,但我有点失望,因为我往往会产生丑陋的解决方案...