clojure - 如何防止Clojure异常: clojure. lang.LazySeq无法转换为clojure.lang.IFn

标签 clojure lazy-sequences

我试图将从映射操作返回的(惰性)序列传递给另一个映射操作,以便我可以查找第一个序列中的元素。该代码从文本文件(行/列格式)中解析一些足球比赛,清理它,然后返回 map 。

这是代码:

(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,将列名称关键字与其在列数据中对应的元素组合起来(请注意,并非所有列都被使用)

问题是,在 zipmap 中使用修剪列会导致

java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

我想我知道为什么会发生这种情况...因为 trimmed-cols 是一个 LazySeq,从 zipmap 调用的映射反对接收非函数作为其第一个参数。

要解决此问题,我可以将 let 更改为:

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

但这感觉不是“最佳”选择。

所以:

  1. 是否有一个好的通用解决方案可以将映射操作的结果用作另一个映射的“函数”参数?
  2. 是否有更好的方法从原始值数据向量导出 {: value} 对的映射(其中未使用所有向量元素)?

(我犹豫是否需要一个惯用的解决方案,但想象在某个地方一定有一种普遍接受的方法来做到这一点。)

最佳答案

我不完全确定你在做什么,但我可以明白为什么你的代码失败 - 就像你说的,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"}

关于clojure - 如何防止Clojure异常: clojure. lang.LazySeq无法转换为clojure.lang.IFn,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8769192/

相关文章:

clojure - Clojure中是否有标准的 “foreach”函数?

list - 在 clojure 中,为什么 "some"函数不能在集合上始终如一地工作?

clojure - 如何展平和延迟连接列表列表

recursion - 堆栈溢出和递归序列表达式 F#

java - 设置我使用 Clojure 对纯 Java 库进行单元测试的环境

algorithm - 对 Clojure 中功能性的广度优先树遍历感到困惑?

parsing - clojure源代码在宏中的位置

Clojure 头保留在剂量中,运行!循环

f# - 函数生成的长度不正确的序列

ruby - 使用索引无限次地做某事