我在考虑如何从*
中构建+
,最后从+
中构建inc
,然后在另一个方向上应用相同的模式使用较低的函数(f a b)
b次,你会得到一个不断增加的超音速的超乘函数的阶梯。所以我决定尝试编写一个不断增加的超级运算符的无限列表。我想出了这个,非常接近! :
(defn operator-staircase
[]
(iterate
(fn [f]
(fn [a b]
(loop [bottom b
result a]
(if (>= 0 bottom)
result
(recur
(dec bottom)
(f a result))))))
(fn [a b]
(inc b))))
(def ops (operator-staircase))
((nth ops 0) 3 5) ;; --> 6 (inc is arity one so it must ignore one of the args?)
((nth ops 1) 3 5) ;; --> 8 (correct addition)
((nth ops 2) 3 5) ;; --> 18 (oops, one off! otherwise correctly multiplies.)
Basically implements (fn [a b] (* a (inc b)))
((nth ops 3) 3 5) ;; ----> 1092 (Wow)
我唯一不知道怎么做的是以一般方式定义初始result
!我只是把它a
因为它有用,但是例如它必须是0,而乘法应该是1.
如何在上面的循环中定义result
的初始值,以便它在所有情况下都能以一般方式工作?
提前致谢!
答案 0 :(得分:1)
我认为如果你想从inc
开始,你只能有意义地定义一元运算符。所以第0步是“加一”;第一步是“N次:加1”,基本上是#(+ % %)
;第二步是“N次:加N”,即#(* % %)
;第三步是“N次:乘以N”,即#(pow % %)
......等等。
如果你想定义二元运算符,我认为你只是从+
开始而不是从inc
开始,并像你一样推导出其余运算符。
答案 1 :(得分:0)
我认为合金说的是正确的。这是我的序列版本,从amalloy建议的+
开始。与您的另一个区别是,我的计数器变量从(dec b)
而不是b
开始。原因是如果你想到例如a*3
为“a
自身添加3次”,这仍然只是添加功能的2个应用(即a+a+a
)。通过这些更改,我得到了我认为您期待的结果。
(def operator-staircase
(iterate
(fn [f]
(fn [a b]
(loop [acc a
counter (dec b)]
(if (>= 0 counter)
acc
(recur (f a acc) (dec counter))))))
+))
;; in comments, * is multiplication, ** is exponentiation (chained multiplication), *** is chained exponentiation, etc
(println ((nth operator-staircase 0) 3 2)) ; 5 = 3+2 = (inc (inc 3)))
(println ((nth operator-staircase 1) 3 2)) ; 6 = 3*2 = 3+3
(println ((nth operator-staircase 2) 3 2)) ; 9 = 3**2 = 3*3 = 3+3+3
(println ((nth operator-staircase 3) 3 2)) ; 27 = 3***2 = 3**3 = 3*3*3
;(println ((nth operator-staircase 4) 3 2)) ; takes too long to compute, but presumably 7625597484987 = 3****2 = 3***3 = 3**(3**3)
(println ((nth operator-staircase 0) 2 3)) ; 5 = 2+3 = (inc (inc (inc 2)))
(println ((nth operator-staircase 1) 2 3)) ; 6 = 2*3 = 2+2+2
(println ((nth operator-staircase 2) 2 3)) ; 8 = 2**3 = 2*2*2 = 2+2+2+2
(println ((nth operator-staircase 3) 2 3)) ; 16 = 2***3 = 2**(2**2) = 2*2*2*2
让我们稍微打破前几次迭代:
(defn apply-n-times [f n arg]
(if (= n 0) arg
(recur f (dec n) (f arg))))
(defn plus [m n]
(apply-n-times inc n m))
(defn times [m n]
(apply-n-times (partial plus m) (dec n) m))
(defn exp [m n]
(apply-n-times (partial times m) (dec n) m))
(defn expexp [m n]
(apply-n-times (partial exp m) (dec n) m))
同样,有必要应用(dec n)
次,而不是n
。如果我应用了n
次,则第三个arg对于times
必须为0,对于exp
必须为1,而不是m
所有,所以会没有统一性。
apply-n-times
功能允许我们更简洁地定义您的操作员楼梯:
(def os2
(iterate
(fn [f]
(fn [m n]
(apply-n-times (partial f m) (dec n) m)))
+))
这个结果与前面的定义相同。但我仍然无法向前迈进一步,并以+
的方式在同一序列中定义inc
。如果您查看plus
与上述其他函数(times
,exp
,expexp
)之间的差异,我认为您可以看到结构不一样。< / p>