Как сделать численное моделирование с неизменными данными в Clojure?

Я использовал django-эволюцию. Протесты включают:

  • Его автоматические предложения были однородно гнилыми; и
  • Его функция цифрового отпечатка возвращает различные значения для той же базы данных по различным платформам.

Однако я нахожу, что пользовательские schema_evolution.py приближаются удобный. Для работы вокруг проблемы цифрового отпечатка я предлагаю код как:

BEFORE = 'fv1:-436177719' # first fingerprint
BEFORE64 = 'fv1:-108578349625146375' # same, but on 64-bit Linux
AFTER = 'fv1:-2132605944' 
AFTER64 = 'fv1:-3559032165562222486'

fingerprints = [
    BEFORE, AFTER,
    BEFORE64, AFTER64,
    ]

CHANGESQL = """
    /* put your SQL code to make the changes here */
    """

evolutions = [
    ((BEFORE, AFTER), CHANGESQL),
    ((BEFORE64, AFTER64), CHANGESQL)
    ]

, Если бы у меня было больше цифровых отпечатков и изменений, я осуществил бы рефакторинг его. До тех пор создание его инструмент для очистки украло бы время разработки из чего-то еще.

РЕДАКТИРОВАНИЕ: , Учитывая, что я вручную создаю свои изменения так или иначе, я попробую dmigrations в следующий раз.

7
задан 17 November 2009 в 11:06
поделиться

4 ответа

(defn run-sim [arr num-iters update-fn]
 (if (zero? num-iters)
   arr
   (let [i (rand-int (count arr))
         x (update-fn)]
     (println "setting arr[" i "] to" x)
     (recur (assoc arr i x) (dec num-iters) update-fn))))

user> (run-sim [1 2 3 4 5 6 7 8 9 10] 10 #(rand-int 1000))
setting arr[ 8 ] to 167
setting arr[ 4 ] to 977
setting arr[ 5 ] to 810
setting arr[ 5 ] to 165
setting arr[ 3 ] to 486
setting arr[ 1 ] to 382
setting arr[ 4 ] to 792
setting arr[ 8 ] to 478
setting arr[ 4 ] to 144
setting arr[ 7 ] to 416
[1 382 3 486 144 165 7 416 478 10]

Нет ничего постыдного в использовании массива Java, если он вам нужен. Особенно, если вам нужно двигаться быстро. Ограничьте изменение массива внутри вашей функции (клонируйте входной массив и, возможно, поработайте над этим), и никто не станет мудрее.

6
ответ дан 6 December 2019 в 15:23
поделиться

Дополнение к ответу Брайана: Если вам нужно больше скорости, вы также можете прибегнуть к переходным процессам.

(defn run-sim
  [vektor num-iters update-fn]
  (loop [vektor    (transient vektor)
         num-iters (int num-iters)]
    (if (zero? num-iters)
      (persistent! vektor)
      (let [i (rand-int (count vektor))
            x (update-fn)]
        (recur (assoc! vektor i x) (dec num-iters))))))
5
ответ дан 6 December 2019 в 15:23
поделиться

Давайте сначала определим функцию, которая обновляет случайный индекс в векторе новым значением. Обратите внимание, что исходный вектор не изменяется, вместо этого возвращается новый вектор (с обновленным значением):

(defn f [xs]
  (let [r (java.util.Random.)
        i (.nextInt r (count xs))
        b (.nextBoolean r)]
    (assoc xs i ((if b inc dec) (xs i)))))

Эта функция выбирает индекс, а затем увеличивает или уменьшает значение этого индекса на 1. Вы, конечно, должны изменить эта функция под ваши нужды.

Тогда несложно скомпоновать эту функцию с собой столько раз, сколько вы хотите запускать симуляцию:

user=> ((apply comp (repeat 1000 f)) [0 0 0 0 0 0 0])
[7 -4 7 6 10 0 -6]
2
ответ дан 6 December 2019 в 15:23
поделиться

Clojure не победил ' t позволяет изменять значения, это немного более громоздко.

(def vec-ref (ref my-vector))

(dosync (set! vec-ref (assoc my-vector index value))

для просмотра значений в измененном векторе используйте @ vec-ref.

Могут быть отключены в деталях - я, к сожалению, не близок к REPL. Но это должно помочь вам начать.

1
ответ дан 6 December 2019 в 15:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: