简短的回答是肯定的,Clojure可以直接与Java数组一起使用,因此直接转换非常简单。
(for [k (range 1 (count a))
y (range 1 b)]
(if (< y (aget a (dec k)))
(aset knap k (dec y) (aget knap (dec k) (dec y))
(if (> y (aget a (dec k)))
(aset knap k (dec y) (max (aget knap (dec k) (dec y))
(aget knap (dec k) (+ (- y 1 (aget a (dec k)))
(aget c (dec k))))
(aset knap k (dec y) (max (aget knap (dec k) (dec y))
(aget c (dec k))))))))))
这段代码不是很符合Clojure编程的惯用方式,因为它把循环与要执行的工作结合在了一起。如果将该循环中的元素分离出来,生成的代码会更加简洁易懂。
作为第一步,我们可以将循环与“工作”分开,代码如下:
(defn edit-array [k y]
(if (< y (aget a (dec k)))
(aset knap k (dec y) (aget knap (dec k) (dec y))
(if (> y (aget a (dec k)))
(aset knap k (dec y) (max (aget knap (dec k) (dec y))
(aget knap (dec k) (+ (- y 1 (aget a (dec k)))
(aget c (dec k))))
(aset knap k (dec y) (max (aget knap (dec k) (dec y))
(aget c (dec k))))))))))
(for [k (range 1 (count a)) y (range 1 b)]
(edit-array k y))
然后我们可以在repl中测试编辑数组,并确信它起作用(也许写一个单元测试)。之后,也许你想开始更仔细地查看
edit-array
并决定是否可能将其分解为更容易独立测试的步骤。也许您可以将其更改为使用函数式风格而不是突变数组。在这里,我会远离您的具体问题,因为我必须承认我不理解这个线性规划解决方案最初设计解决的问题。
(defn finished? [row] ... determine if we have reached the final state ...)
(defn next-row [current-row]
(for [y (range 1 (count current-row)]
... code to produce a new vector based on the previous one ...))
(take-while #(not (finished? %) (iterate next-row (initial-state)))
我认为符合惯用的Clojure代码的基本概念是将问题分解成简单(只做一件事)的抽象,然后组合它们来解决主要问题。当然,这必须始终根据手头的问题进行调整。