【问题标题】:Clojure loop receiving IllegalArgumentException Key must be integer clojure.lang.APersistentVector.invokeClojure 循环接收 IllegalArgumentException Key 必须是整数 clojure.lang.APersistentVector.invoke
【发布时间】:2015-06-07 23:48:31
【问题描述】:

我一直试图让 Clojure 中的一个简单循环正常工作,但我不知道如何继续摆脱异常。我正在尝试将arrange 函数写入向量中的exchange 项目。这是代码。

(defn exchange [v i] 
  (let [[src dst] i]
    (assoc v dst (v src) src (v dst))))

(defn arrange []
  (loop [idxs [0 0] 
         deck [\a \b \c \d \e] 
         pts [[0 1] [2 3] [4 1]]]
    (println idxs deck pts)
    (empty? pts)
      deck
      (recur (first pts) (exchange deck idxs) (rest pts))))    

;(arrange)
;[b e d c a]

如果我删除 println,我在 REPL 中看不到任何内容。我来自 COBOL,所以你知道我在努力学习这个:) 任何让这个更惯用的建议都将不胜感激。

6/11- 这是更正后的代码。 arrange 在循环中应该只有两个参数。

(defn arrange []
  (loop [deck [\a \b \c \d \e] 
         lst [[0 1] [2 3] [4 1]]]
    (if (empty? lst)
      deck
      (recur (exchange deck (first lst)) (rest lst)))))

或者更好的是,使用(reduce exchange deck lst) 代替@Magos!

【问题讨论】:

  • 我看到你已经在你的loop 上得到了一个很好的答案,所以我只想提一下exchange 是一种二元运算符reduce 是为(接受一个“到目前为止的值”和另一个独立类型的值,产生另一个“迄今为止的值”),因此您在arrange 中的loop 基本上是为一个特定的运算符重新实现reduce。您也可以使用(reduce exchange [\a \b \c \d \e] [[0 1] [2 3] [4 1]])
  • 这正是我正在寻找的建议!非常感谢您抽出宝贵时间对我的问题发表评论。
  • 如果我将 pts 更改为 [[1 4] [1 3] [4 0]] 然后 arrange 返回 (\b \e \c \d \a) 但 (reduce exchange [\a \b \c \d \e] [[1 4] [1 3] [4 0]]) 返回 [ \b \d \c \e \a] 所以排列和减少+交换的工作方式似乎有点不同。也许还有一种方法可以利用reduce?
  • 如果我以(if (empty? pts) 离开测试,我得到的结果与reduce 相同。
  • 那很奇怪。将arrange 与@bsvingens 的建议和您的新pts 一起使用,我得到[\b \d \c \e \a],就像reduce 一样。您是否还可以将初始绑定更改为idxs?如果是这样,您需要将该向量添加到 reduce 的参数前面以产生相同的效果。 ([0 0] 给出的 exchange 不会导致任何更改,所以我没有包含它)

标签: clojure


【解决方案1】:

您缺少if,您需要在idxs 上结束循环,而不是pts(否则您将错过最终的索引对):

(if (empty? idxs)
  deck
  (recur (first pts) (exchange deck idxs) (rest pts)))

应该会更好。

【讨论】:

  • 非常感谢!我知道这很简单,但我看不到。也用于指出我的条件中的错误。我尝试 +1,但它说我需要 15 声望 :(
猜你喜欢
  • 2020-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
  • 1970-01-01
  • 1970-01-01
  • 2019-10-15
  • 1970-01-01
相关资源
最近更新 更多