Определение объекта карты внутри цикла recur - Clojure

Я пытаюсь использовать recur цикла, который создает пустую карту внутри цикла. Для каждой записи в цикле (петли через вектор карт) он увидит, есть ли ключ во вновь созданной карте, который соответствует итерированному значению, и если он не создан.

Я создал этот код:

(def meteor-map (json/read-str (clojure.string/lower-case
(slurp "https://data.nasa.gov/resource/y77d-th95.json"))))

(defn most-falls [values]
(loop [values map count-tracker{}]
  (if (empty? values)
    (count-tracker)
    (do
      (def key (keyword (get (first values) "year")))
      (if (contains? (first values) key)
        (do
          (def count-tracker (update count-tracker key inc))
          (recur (rest values) count-tracker)
        )
        (do
          (def count-tracker (assoc count-tracker key 1))
          (recur (rest values) count-tracker)
        )
      )
    )
  )
)
)

(most-falls meteor-map)

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

неверное количество аргументов (0), переданных в persistentarraymap

Я думаю, это может быть связано с тем, как я создаю начальный объект count-tracker внутри создания цикла, но я не уверен.

Есть идеи?

благодаря

PS знаю, что этот вопрос немного расплывчатый, поэтому любые вопросы просто спрашивают!

0
Какая ошибка? Проблема заключается в том, что ваш код представляет собой несколько проблем (с помощью def и [значения map в цикле )), поэтому трудно точно определить, что именно идет не так.
добавлено автор Carcigenicate, источник
Что означает (count-tracker) , который должен выполняться? Это твоя ошибка. Вы пытаетесь вызвать карту без аргументов. Если вы исправите это, то values ​​map даст вам ошибку, так как функция map является функцией. Я думаю, вы просто имели в виду значения значений .
добавлено автор Carcigenicate, источник
Но что вы пытаетесь сделать с (count-tracker) ? Просто верните count-tracker ? Затем удалите круглую скобку вокруг него. Помните, если вы что-то окружаете в круглых скобках, вы называете это функцией.
добавлено автор Carcigenicate, источник
Я пишу ответ, так как у вас есть несколько вещей, о которых стоит упомянуть. Дайте мне пару минут.
добавлено автор Carcigenicate, источник
@Carcigenicate count-tracker должен быть пустой картой, которую я создаю, а затем добавляю/обновляю ключи в зависимости от значения, которое в данный момент находится в цикле. Например, если первое значение имеет год: «1996», и он еще не существует в count-tracker, он добавит этот ключ к этой карте. Если он уже существовал, значение (например: 1996 1) будет увеличиваться. надеюсь, что это имеет смысл!
добавлено автор broliverparker, источник
@Carcigenicate, который решил мою проблему, спасибо большое!
добавлено автор broliverparker, источник

8 ответы

Здесь много вещей, которые нужно воспитать. Основная проблема заключается в том, что (count-tracker) . Вы окружите карту в скобках, а это означает, что вы хотите назвать ее функцией. Вы не можете произвольно добавлять скобки в код, как вы можете, на других языках; он имеет специфическое значение very в Clojure. (f) always означает, что вызывается функция f . Просто измените его на count-tracker , чтобы вернуть значение.

Другие вещи:

  • NEVER use def inside of a function unless it's necessary. In this case though, it's entirely unnecessary. Every use of def creates globals that last for the length of the program (yes, they exist even after the function exits!). Use let instead:

    (let [key (keyword (get (first values) "year")))]
       ... ) ; Use key here
    
  • (loop [values map ...] will cause errors as well. map is a function, so this throws away the argument passed in to most-falls, overwriting it with the map function. This will cause an error when you try to use values as a sequence, since the map function doesn't support empty? or first, or anything else you're trying to use it for. I think you just intended to just rebind the argument to be used in the loop. Just change it to (loop [values values ...]. Arguably, you shouldn't shadow arguments by creating other bindings with the same name, but that's not exceedingly important here.

Есть еще несколько других мелочей, которые можно улучшить. Используя деструктурирование, вы можете пропустить вызовы first и rest , а с помощью уменьшить может упростить явный цикл с помощью цикла , но это будет отвлекать от основных вопросов. Принимая во внимание то, что я упомянул выше, я бы написал вашу функцию как:

(defn most-falls [values]
  (loop [values values
         count-tracker {}]
    (if (empty? values)
      count-tracker
      (let [key (keyword (get (first values) "year"))]
        (recur (rest values)
               (if (contains? (first values) key)
                 (update count-tracker key inc)
                 (assoc count-tracker key 1)))))))
3
добавлено

Здесь много вещей, которые нужно воспитать. Основная проблема заключается в том, что (count-tracker) . Вы окружите карту в скобках, а это означает, что вы хотите назвать ее функцией. Вы не можете произвольно добавлять скобки в код, как вы можете, на других языках; он имеет специфическое значение very в Clojure. (f) always означает, что вызывается функция f . Просто измените его на count-tracker , чтобы вернуть значение.

Другие вещи:

  • NEVER use def inside of a function unless it's necessary. In this case though, it's entirely unnecessary. Every use of def creates globals that last for the length of the program (yes, they exist even after the function exits!). Use let instead:

    (let [key (keyword (get (first values) "year")))]
       ... ) ; Use key here
    
  • (loop [values map ...] will cause errors as well. map is a function, so this throws away the argument passed in to most-falls, overwriting it with the map function. This will cause an error when you try to use values as a sequence, since the map function doesn't support empty? or first, or anything else you're trying to use it for. I think you just intended to just rebind the argument to be used in the loop. Just change it to (loop [values values ...]. Arguably, you shouldn't shadow arguments by creating other bindings with the same name, but that's not exceedingly important here.

Есть еще несколько других мелочей, которые можно улучшить. Используя деструктурирование, вы можете пропустить вызовы first и rest , а с помощью уменьшить может упростить явный цикл с помощью цикла , но это будет отвлекать от основных вопросов. Принимая во внимание то, что я упомянул выше, я бы написал вашу функцию как:

(defn most-falls [values]
  (loop [values values
         count-tracker {}]
    (if (empty? values)
      count-tracker
      (let [key (keyword (get (first values) "year"))]
        (recur (rest values)
               (if (contains? (first values) key)
                 (update count-tracker key inc)
                 (assoc count-tracker key 1)))))))
3
добавлено

Здесь много вещей, которые нужно воспитать. Основная проблема заключается в том, что (count-tracker) . Вы окружите карту в скобках, а это означает, что вы хотите назвать ее функцией. Вы не можете произвольно добавлять скобки в код, как вы можете, на других языках; он имеет специфическое значение very в Clojure. (f) always означает, что вызывается функция f . Просто измените его на count-tracker , чтобы вернуть значение.

Другие вещи:

  • NEVER use def inside of a function unless it's necessary. In this case though, it's entirely unnecessary. Every use of def creates globals that last for the length of the program (yes, they exist even after the function exits!). Use let instead:

    (let [key (keyword (get (first values) "year")))]
       ... ) ; Use key here
    
  • (loop [values map ...] will cause errors as well. map is a function, so this throws away the argument passed in to most-falls, overwriting it with the map function. This will cause an error when you try to use values as a sequence, since the map function doesn't support empty? or first, or anything else you're trying to use it for. I think you just intended to just rebind the argument to be used in the loop. Just change it to (loop [values values ...]. Arguably, you shouldn't shadow arguments by creating other bindings with the same name, but that's not exceedingly important here.

Есть еще несколько других мелочей, которые можно улучшить. Используя деструктурирование, вы можете пропустить вызовы first и rest , а с помощью уменьшить может упростить явный цикл с помощью цикла , но это будет отвлекать от основных вопросов. Принимая во внимание то, что я упомянул выше, я бы написал вашу функцию как:

(defn most-falls [values]
  (loop [values values
         count-tracker {}]
    (if (empty? values)
      count-tracker
      (let [key (keyword (get (first values) "year"))]
        (recur (rest values)
               (if (contains? (first values) key)
                 (update count-tracker key inc)
                 (assoc count-tracker key 1)))))))
3
добавлено

Здесь много вещей, которые нужно воспитать. Основная проблема заключается в том, что (count-tracker) . Вы окружите карту в скобках, а это означает, что вы хотите назвать ее функцией. Вы не можете произвольно добавлять скобки в код, как вы можете, на других языках; он имеет специфическое значение very в Clojure. (f) always означает, что вызывается функция f . Просто измените его на count-tracker , чтобы вернуть значение.

Другие вещи:

  • NEVER use def inside of a function unless it's necessary. In this case though, it's entirely unnecessary. Every use of def creates globals that last for the length of the program (yes, they exist even after the function exits!). Use let instead:

    (let [key (keyword (get (first values) "year")))]
       ... ) ; Use key here
    
  • (loop [values map ...] will cause errors as well. map is a function, so this throws away the argument passed in to most-falls, overwriting it with the map function. This will cause an error when you try to use values as a sequence, since the map function doesn't support empty? or first, or anything else you're trying to use it for. I think you just intended to just rebind the argument to be used in the loop. Just change it to (loop [values values ...]. Arguably, you shouldn't shadow arguments by creating other bindings with the same name, but that's not exceedingly important here.

Есть еще несколько других мелочей, которые можно улучшить. Используя деструктурирование, вы можете пропустить вызовы first и rest , а с помощью уменьшить может упростить явный цикл с помощью цикла , но это будет отвлекать от основных вопросов. Принимая во внимание то, что я упомянул выше, я бы написал вашу функцию как:

(defn most-falls [values]
  (loop [values values
         count-tracker {}]
    (if (empty? values)
      count-tracker
      (let [key (keyword (get (first values) "year"))]
        (recur (rest values)
               (if (contains? (first values) key)
                 (update count-tracker key inc)
                 (assoc count-tracker key 1)))))))
3
добавлено

Во-первых, в этой статье определенно есть проблема:

(loop [values map count-tracker{}]

Я не использую то, что вы пытались достичь, но, пожалуйста, взгляните.

Затем никогда не используйте def или defn формы внутри кода, только на верхнем уровне пространства имен.

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

Внутри этой функции вы решаете, имеет ли ваша карта какой-то конкретный ключ и добавляет ее, если это не так.

Краткий пример:

# here are some data you've read from a file
(def items [{...} {...} {...}])

# reduce process function
(defn process
  [result item]
  (if (:some-key result) ;; here, you check the current map for a key
    result               ;; return the old map if everything is ok
    (assoc result :some-key some-data)))  ;; accumulate a new key into a map

(reduce process {} items)
1
добавлено

Во-первых, в этой статье определенно есть проблема:

(loop [values map count-tracker{}]

Я не использую то, что вы пытались достичь, но, пожалуйста, взгляните.

Затем никогда не используйте def или defn формы внутри кода, только на верхнем уровне пространства имен.

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

Внутри этой функции вы решаете, имеет ли ваша карта какой-то конкретный ключ и добавляет ее, если это не так.

Краткий пример:

# here are some data you've read from a file
(def items [{...} {...} {...}])

# reduce process function
(defn process
  [result item]
  (if (:some-key result) ;; here, you check the current map for a key
    result               ;; return the old map if everything is ok
    (assoc result :some-key some-data)))  ;; accumulate a new key into a map

(reduce process {} items)
1
добавлено

Во-первых, в этой статье определенно есть проблема:

(loop [values map count-tracker{}]

Я не использую то, что вы пытались достичь, но, пожалуйста, взгляните.

Затем никогда не используйте def или defn формы внутри кода, только на верхнем уровне пространства имен.

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

Внутри этой функции вы решаете, имеет ли ваша карта какой-то конкретный ключ и добавляет ее, если это не так.

Краткий пример:

# here are some data you've read from a file
(def items [{...} {...} {...}])

# reduce process function
(defn process
  [result item]
  (if (:some-key result) ;; here, you check the current map for a key
    result               ;; return the old map if everything is ok
    (assoc result :some-key some-data)))  ;; accumulate a new key into a map

(reduce process {} items)
1
добавлено

Во-первых, в этой статье определенно есть проблема:

(loop [values map count-tracker{}]

Я не использую то, что вы пытались достичь, но, пожалуйста, взгляните.

Затем никогда не используйте def или defn формы внутри кода, только на верхнем уровне пространства имен.

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

Внутри этой функции вы решаете, имеет ли ваша карта какой-то конкретный ключ и добавляет ее, если это не так.

Краткий пример:

# here are some data you've read from a file
(def items [{...} {...} {...}])

# reduce process function
(defn process
  [result item]
  (if (:some-key result) ;; here, you check the current map for a key
    result               ;; return the old map if everything is ok
    (assoc result :some-key some-data)))  ;; accumulate a new key into a map

(reduce process {} items)
1
добавлено
JavaScript Jobs — чат
JavaScript Jobs — чат
8 336 участник(ов)

JavaScript Jobs — чат для поиска работы и людей Правила оформления: https://teletype.in/@telegram-ru/r1WQe5F1m См. также: @mobile_jobs, @devops_jobs, @nodejs_jobs, @react_js, @angular_ru, @js_ru

JavaScript.ru
JavaScript.ru
7 932 участник(ов)

Сообщество сайта JavaScript.ru в Slack.

pro.js
pro.js
4 675 участник(ов)

Про JavaScript и NodeJS Invite: https://t.me/joinchat/Be4rsT5Rsgq30DHutjxXgA Правила: http://telegra.ph/ru-chat-rules-06-19 Вакансии только с ЗП, не чаще раза в неделю.

pro.jvm
pro.jvm
3 503 участник(ов)

Сообщество разработчиков Java Scala Kotlin Groovy Clojure Чат для нач-их: @javastart Наш сайт: projvm.com projvm.ru Наш канал: @proJVM Вакансии: @jvmjobs Конфы: @jvmconf

JavaScript — русскоговорящее сообщество
JavaScript — русскоговорящее сообщество
3 269 участник(ов)

Рекомендуем сразу отключить уведомления Правила: https://rudevs.network/ByaMH6un7 См. также: @js_noobs_ru, @nodejs_ru, @typescript_ru, @react_js, @electron_ru Вакансии и поиск работы: @javascript_jobs

JavaScript Noobs — сообщество новичков
JavaScript Noobs — сообщество новичков
2 484 участник(ов)

Чат для новичков

javascript_ru
javascript_ru
915 участник(ов)

Сообщество любителей самого популярного языка программирования в мире. Чат основан в 2009 году. Логи: https://goo.gl/9EOeM7 Поддержка бота: @chat_linker (ссылка на репу внутри) Вам будут интересны @frontend_ru и @css_ru

jsChat
jsChat
603 участник(ов)

Чат посвященный программированию на языке javaScript Перед отправкой ссылки на Ваш контент посоветуйтесь с админом Все ссылки удаляются ботом автоматически

JavaScript for Zombies Chat
JavaScript for Zombies Chat
492 участник(ов)

Чат про JavaScript для настоящих zombie! Вход строго по приглашениям! Ссылка для строгих приглашений: https://t.me/joinchat/AAMBHz3Uyr0tuZ7VaB029g

Clojure — русскоговорящее сообщество
Clojure — русскоговорящее сообщество
433 участник(ов)

Общаемся на темы, посвященный Clojure. Решаем проблемы, обмениваемся опытом и делимся новостями. Вакансии и поиск работы: @clojure_jobs Вам могут быть интересны: @javascript_ru, @nodejs_ru, @ruby_ru, @devops_ru, @devops_jobs

All That JS
All That JS
417 участник(ов)

JS на русском

ФП
ФП
179 участник(ов)

Все о функциональных языках