Как предотвратить исключение Clojure: clojure.lang.LazySeq не может быть приведен к clojure.lang.IFn - PullRequest
2 голосов
/ 07 января 2012

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

Вот код:

(ns fixtures.test.lazytest
  (:require [clojure.string :as str])
  (:use [clojure.test]))

(defn- column-map
  "Produce map with column labels given raw data, return nil if not enough columns"
  [cols]
  (let [trimmed-cols (map str/trim cols)
        column-names {0 :fixture-type, 1 :division, 2 :home-team, 4 :away-team}]
    (if (> (count cols) (apply max (keys column-names)))
      (zipmap (vals column-names) (map trimmed-cols (keys column-names)))
      nil)))

(deftest test-mapping
  (let [cols '["L" "   Premier " "  Chelsea  " "v" "\tArsenal  "]
        fixture (column-map cols)]
    (is (= "Arsenal" (fixture :away-team)))
    (is (= "Chelsea" (fixture :home-team)))
    (is (= "Premier" (fixture :division)))
    (is (= "L" (fixture :fixture-type)))
  )
)

(run-tests 'fixtures.test.lazytest)

Я использую следующий подход:

  1. Очистить вектор данных столбца (удалить пробелы в начале / конце)
  2. Используя zipmap, объедините ключевые слова имени столбца с их соответствующим элементом в столбце.данные (обратите внимание, что используются не все столбцы)

Проблема в том, что использование trimmed-cols в zipmap приводит к

java.lang.ClassCastException: clojure.lang.LazySeq не может быть приведен к clojure.lang.IFn

Я думаю, я знаю, почему это происходит ... поскольку trimmed-cols является LazySeq,карта, вызванная из zipmap, возражает против получения не-функции в качестве первого аргумента.

Чтобы исправить это, я могу изменить let на:

trimmed-cols (vec (map str/trim cols))

Ноэто не похоже на «лучший» вариант.

Итак:

  1. Есть хороший генКакое решение использовать результат операции карты в качестве аргумента «функции» для другой карты?
  2. Существует ли лучший подход для получения карты пар {: value} из вектора необработанных данных значений, гдене все элементы вектора используются?

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

1 Ответ

3 голосов
/ 07 января 2012

Я не совсем уверен, что вы ищете, но я понимаю, почему ваш код не работает - как вы сказали, trimmed-cols не является функцией.Разве это не сработает?

Я использую :_dummy ключи для столбцов, которые следует пропустить.Вы можете использовать сколько угодно в векторе column-names: zipmap объединит их в один, который удаляется с помощью dissoc.

(defn- column-map
  "Produce map with column labels given raw data, return nil if not enough columns"
  [cols]
  (let [trimmed-cols (map str/trim cols)
        column-names [:fixture-type :division :home-team :_dummy :away-team]]
    (if (>= (count cols) (count column-names))
      (dissoc (zipmap column-names trimmed-cols) :_dummy)
      nil)))

(column-map ["L" "   Premier " "  Chelsea  " "v" "\tArsenal  "])
; => {:away-team "Arsenal", :home-team "Chelsea", :division "Premier", :fixture-type "L"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...