Как реализовать цикл For в Clojure - PullRequest
25 голосов
/ 02 апреля 2012

Я хотел бы реализовать этот маленький код в Clojure, но я изо всех сил:

struct mystruct {
   int id;
   int price;
};

mystruct mydata[10];

for (int i=0; i<10; i++) {
  myfunction(mydata[i].id, mydata[i].price);
  //other things...
}

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

Я был бы очень признателен, если бы кто-нибудь мог мне помочь.Спасибо !!

Ответы [ 2 ]

36 голосов
/ 02 апреля 2012

Один из способов перевести обязательный цикл в Clojure - использовать макрос for.

(for [i (range 10)] (inc i))

Вышеприведенная функция вернет все числа от 0 до 9, увеличенные на 1. Однако, похоже, вы просто хотите перебрать последовательную коллекцию и использовать каждый элемент. Если это все, что вам нужно, вам не нужно ссылаться на значение индекса, вместо этого вы можете ссылаться на каждый элемент напрямую.

(for [d my-vec-of-data] (my-function d))

Однако, для этого простого случая, функция map, вероятно, будет лучшим выбором, потому что она предназначена для вызова функций с аргументами из коллекций. Следующий пример эквивалентен использованию for выше.

(map my-function my-vec-of-data)

И map, и for возвращают коллекцию значений, составленную из значений, возвращаемых my-function. Это потому, что структуры данных Clojure неизменны, поэтому необходимо вернуть новую коллекцию. Если это не то, что вам нужно, или если ваша функция имеет побочные эффекты, вы можете использовать doseq вместо for, что возвращает nil.

33 голосов
/ 07 апреля 2012

Ответ Джереми хорош для того, как сделать цикл for в идиоматическом Clojure.

Если вы действительно хотите использовать цикл в императивном стиле в Clojure, вы можете создать его с помощью этого макроса:

(defmacro for-loop [[sym init check change :as params] & steps]
 `(loop [~sym ~init value# nil]
    (if ~check
      (let [new-value# (do ~@steps)]
        (recur ~change new-value#))
      value#)))

Использование следующим образом:

(for-loop [i 0 (< i 10) (inc i)] 
  (println i))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...