Как получить случайный доступ по индексу на хэш-карте в Clojure? - PullRequest
3 голосов
/ 05 марта 2012

Я хотел бы выполнить несколько (MAX_OPERATIONS) денежных переводов с одного счета на другой. Счета хранятся в виде ссылок в вызывающей программе хэш-карты my-map (int account-id, двойной баланс).

Денежный перевод берет "случайный индекс" с хэш-карты и передает его как account-from в transfer. account-destination и amount должны быть исправлены.

К сожалению, я не могу заставить это работать.

(defn transfer [from-account to-account amount]
  (dosync
    (if (> amount @from-account)
      (throw (Exception.  "Not enough money")))
    (alter from-account - amount)
    (alter to-account + amount)))

(defn transfer-all []
  (dotimes [MAX_OPERATIONS]
    (transfer (get mymap (rand-int[MAX_ACCOUNT]) :account-id) account-destination amount)))

Ответы [ 2 ]

5 голосов
/ 06 марта 2012

Карты не влияют на nth, поэтому вам нужно использовать промежуточную структуру, которая влияет на nth. Вы можете сделать последовательность из нескольких ключей или всех записей карты в зависимости от того, что вы хотите получить. Мне нравится использовать rand-nth для такого рода вещей, потому что он хорошо читается

вы можете получить nth способный набор ключей, а затем использовать один из них случайным образом:

user> (def mymap {:a 1, :b 2, :c 3})
#'user/mymap
user> (get mymap (rand-nth (keys mymap)))
1
user> (get mymap (rand-nth (keys mymap)))
1
user> (get mymap (rand-nth (keys mymap)))
3

Или вы можете превратить карту в nth способный вектор, а затем взять его случайным образом

user> (rand-nth (vec mymap))
[:a 1]
user> (rand-nth (vec mymap))
[:c 3]
5 голосов
/ 05 марта 2012

Я вижу сразу несколько проблем:

Ваш синтаксис для dotimes неправильный, вам нужно включить переменную цикла.Что-то вроде:

(dotimes [i MAX_OPERATIONS]
   ....)

Также rand-int просто нужен целочисленный параметр, а не вектор, что-то вроде:

(rand-int MAX_ACCOUNT)

Кроме того, я не уверен, что ваш (получите...) вызов делает именно то, что вы намерены.Как написано в настоящее время, он вернет ключевое слово :account-id, если не найдет случайно сгенерированный целочисленный ключ, что вызовет проблемы, поскольку передаточная функция требует двух ссылок как от учетной записи до учетной записи.

Как более общий совет, вам, вероятно, следует попытаться кодировать это по крупицам в REPL, проверяя, что каждая часть работает так, как задумано.Часто это лучший способ разработки в Clojure - если вы пишете слишком много кода сразу, не тестируя его, то, скорее всего, в нем будет несколько ошибок, и вы можете потеряться, пытаясь отследить корень проблемы.

...