2013-06-10 2 views
1

EDIT: Это не было проблемой при уменьшении или уменьшении функции. Я затенял функцию clojure.core/range.Странное поведение уменьшения в Clojure

У меня есть функция

(defn- roundfn [[xi ci bi oi :as state] r] 
    (let [[xn cn bn] (newstate [xi ci bi] 0) 
     exfn (word<-x xn)] 
    [xn cn bn 
    (into oi 
      [(exfn [6 3 6 1]) 
      (exfn [4 1 4 7]) 
      (exfn [2 7 2 5]) 
      (exfn [0 5 0 3])])])) 

, где x1, x2, x4 и сами являются векторами. x3 - значение.

Когда я уменьшить эту функцию как

(reduce roundfn [[][] 0 []] (range 3)) 

или

(reduce roundfn [[][] 0 []] (vec (range 3))) 

Я получаю IndexOutOfBoundsException clojure.lang.PersistentVector.arrayFor (PersistentVector.java:107)

Когда я уменьшить эту функцию как

(reduce roundfn [[][] 0 []] [0 1 2]) 

работает, как ожидалось

+0

Что 'roundfn' делать? –

+0

Не уверен, что вы видели мои изменения, но 'roundfn' пересчитывает значения в x1 и x2 с помощью x3. Это новое состояние используется для вычисления выходного сигнала, который входит в 4-й вектор. В принципе, первые три элемента представляют текущее состояние, а четвертое - сбор данных на основе этого состояния. Вызов функции bumps в следующее состояние и добавление к выходу на основе этого состояния. –

+0

Я думаю, проблема в 'roundfn'. Если вы просто вернете 'xs' из' roundfn', нет 'IndexOutOfBoundsException'. Без кода для этой функции очень сложно понять, что вызывает проблему. –

ответ

0

Я затенения функции clojure.core\range с моим [lower upper :as range] деструктуризации

Ниже версия, которая не работала

(generate-keystream [_ {:keys [ss] :as initmap} [lower upper :as range]] 
    (let [ns (conj ss [])] 
    (reduce rabbit-round ns (range 3)))) 

следующие работы, как и ожидалось (обратите внимание на изменения в :as rng вместо :as range)

(generate-keystream [_ {:keys [ss] :as initmap} [lower upper :as rng]] 
    (let [ns (conj ss [])] 
    (reduce rabbit-round ns (range 3)))) 

Это объясняет, почему (range 3) и (vec (range 3)) оба не работали, но [0 1 2] сделал. Первые два оценивали ([0 0] 3) и (vec ([0 0] 3)) в моем первоначальном коде, а [0 1 2] оценили по: [0 1 2] и преуспел.

Извлеченный урок. Не теневые функции

В качестве примечания, это тоже работает ...

(generate-keystream [_ {:keys [ss] :as initmap} [lower upper :as range]] 
    (let [ns (conj ss [])] 
    (reduce rabbit-round ns (clojure.core/range 3)))) 
2

(Отработка this version of the source. - ссылка на текущей версии файла, упомянутого в комментарии по этому вопросу)

Во-первых, запуск кода производит исключение в моем РЕПЛ во всех перечисленных вами случаях, включая букву [0 1 2]. Было бы поразительно, если бы это было не так. (NB. Я использую rabbit-round вместо roundfn, так как это функция, указанная в тексте вопроса, найденная в источнике на GitHub.)

Источник проблемы выглядит следующим образом (по ссылке в полном объеме источник дал в комментарии по этому вопросу):

  1. функция перечислены roundfn в тексте вопроса называется в источнике rabbit-round. Проблемный вызов - (reduce rabbit-round [[] [] 0 []] [0 1 2]).

  2. reduce чем звонки rabbit-round с начальными аргументами; в этом случае происходит вызов roundfn (roundfn - отдельная функция в исходном источнике): (roundfn [[] [] 0] 0). Именно здесь исключается исключение.

  3. roundfn представляет собой композицию из двух функций; уже первый оказывается источником проблемы: (update-counter-system [[] [] 0] 0) throws.

  4. Здесь есть reduce, используя counter-system-round в качестве функции уменьшения. Исключение выдается при первом применении последнего: (counter-system-round [[] 0] 0).

  5. Рассматривая counter-system-round, мы видим, что он пытается вычислить (nth c round) в первой строке. На данный момент c привязан к [] (пустой вектор) и round будет 0. Таким образом, этот вызов составляет (nth [] 0) и правильно выбрасывает IndexOutOfBoundsException.

Смежные вопросы