请在2024 Clojure 研究调查中分享您的想法!

欢迎!请参阅关于页面以获取更多关于此的信息。

0
序列

你好,在读取文件中的单词并将其reduce到映射后

{aabdgoo (abogado), aaceilmnotx (exclamation), ehpryz (zephyr), eirt (tire rite), ghirt (right)}

然后过滤后,我得到这个

([aabdgoo (abogado)] [aaceilmnotx (exclamation)] [eirt (tire rite)] [ghirt (right)])

我可以运行 valskeys 函数,以及对此进行进一步 reductions 而无问题。

我想按顺序对每个向量中第二个位置的单词列表进行排序,并认为遍历此结构将非常简单,但经过数小时的迭代,我无法让它工作。

(map #('((first %) (second %))) input) 在map行抛出 执行错误 (ClassCastException):`class clojure.lang.PersistentList cannot be cast to class clojure.lang.IFn (clojure.lang.PersistentList and clojure.lang.IFn are in unnamed module of loader 'app')`。

(map #([(first %) (second %)]) input) 让工具抱怨 `Vector can only be called with 1 arg but was called with: 0`。

(map #(vector (first %) (second %)) input) 在几行后调用 keys 时抛出 `执行错误 (ClassCastException):`class clojure.lang.PersistentVector cannot be cast to class java.util.Map$Entry (clojure.lang.PersistentVector is in unnamed module of loader 'app'; java.util.Map$Entry is in module java.base of loader 'bootstrap')`。

我不知道它在寻找什么。我在哪里做错了?

谢谢

1 答案

+1
回答 Eugene Pakhomov

您可以将这对列表(向量)列表转换为地图,使用(into {} ...)(这还允许您使用转换器,查看)。然后您就可以使用update-vals

(map#endif('((first %) (second %))) input)引发错误

读取器将#(...)展开为(fn* [p1__9#] ((quote ((first p1__9#) (second p1__9#))))) - 您可以使用(macroexpand-1'#(...))进行查看。

quote ...的结果是一个列表,然后您正在调用这个列表,这就是异常产生的地方。

(map #(vector (first %) (second %)) input)导致工具出现错误

类似的情况 - #(...)展开成试图立即调用[...]的结果作为一个没有参数的函数。

(map #(vector (first %) (second %)) input)几行之后抛出Execution error (ClassCastException)

将地图视为序列给您一个具有实现java.util.Map$Entry类型的键值对序列。期望在地图上调用keys函数,而不是在随机的序列上调用,它恰好可以与键值对序列一起使用,但它期望每个对都是一个适当的Map$Entry接口实例。
通过使用那个(vector ...),您将每个地图条目转换为不实现该接口的向量。

一些通用建议

  • 对于键值对,请使用keyval而不是firstsecond - 它们也期望一个地图条目,如果出现问题,将失败得更快,使解决问题变得更简单。它们也更快,并且更能说明代码的意图。
  • 如果您在#(...)上有问题,请尝试将其写成带适当命名参数的(fn [...] ...)(例如,不是x而是kv-pair - 听起来不多但有助于您陷入困境时解决问题)。
  • 如果您遇到ClassCastException,请仔细阅读您正在调用的函数的文档。
  • 当您看到异常时,查阅它的堆栈跟踪,并尝试找出到底出了什么问题。一开始可能会有些困难,但随着时间的推移,至少在大多数情况下,将会变得容易。
...