короткий ответ - да, 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)))
Основное представление о том, что я вижу в коде Idomatic Clojure, состоит в том, чтобы разбить задачу на простые (делает только одно) абстракции, а затем скомпоновать их для решения основной проблемы. Конечно, это всегда должно быть адаптировано к конкретной проблеме.