【问题标题】:Why does recur expect one argument to a short form func using %&为什么 recur 期望使用 %& 的短格式 func 有一个参数
【发布时间】:2012-05-12 02:06:46
【问题描述】:

注意:不是Why does Clojure recur think it should only have one argument? 的重复项。我没有使用循环。

(def t 
  #(let [[low high] (sort %&)] {:low low :high h}))

(t 3 2)
=> {:low 2, :high 3}

鉴于这按预期工作。这怎么不行:

(def t 
  #(let [[low high] (sort %&)] 
    (if (= 0 low)
      nil
      (do
        (println {:low low :high high})
        (recur low (dec high))))))

(t 3 2)
=> java.lang.IllegalArgumentException: Mismatched argument count to recur, expected: 1 args, got: 2

鉴于它说它需要 1 个参数,我可以猜测我可以通过将参数转换为集合来使其工作:

(def t
  #(let [[low high] (sort %&)]
    (if (= 0 low)
      nil
      (do
        (println {:low low :high high})
        (recur [low (dec high)])))))

(t 3 2)
=> {:low 2, :high 3}
   {:low 2, :high 2}
   {:low 1, :high 2}
   {:low 1, :high 1}
   nil

...但是为什么呢?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    这就是它的设计方式。 Clojure website 说:

    递归表达式必须与递归点的数量完全匹配。特别是,如果递归点是可变参数 fn 方法的顶部,则不会收集其余参数 - 应该传递单个 seq(或 null)。

    我认为它是这样设计的,因为如果函数本身给你一个序列(而不是单个参数),那么递归形式会更自然地接受一个序列,或者可以成为一个序列的东西。如果不是这种情况,则需要拆分给定的序列以执行递归。

    您的示例似乎不符合标准,因为看起来您真的只关心有两个参数,这意味着您真的不需要其余的参数。您可能最好明确定义两个参数并在 let 语句中确定哪个低和哪个高,而不是对其余的参数进行排序并解构它们。

    这是您的代码,修改最少。我将两个显式参数包装在一个向量中,然后将它们传递给 sort(基本上模仿了 rest args),并将两个参数传递给 recur。

    (def t
      #(let [[low high] (sort [%1 %2])]
        (if (= 0 low)
          nil
          (do
            (println {:low low :high high})
            (recur low (dec high))))))
    

    但是,在保持递归形式的同时,我可能会稍微重构一下:

    (defn t [x y]
      (let [low (min x y) high (max x y)]
        (when-not (zero? low)
          (println {:low low :high high})
          (recur low (dec high)))))
    

    【讨论】:

    • 为了好玩,我创建了一个没有重复的惰性版本:refheap.com/paste/2691
    • 感谢您的回答。我查找了函数定义特殊形式,但没有想到要查找重复。该代码只是一个做某事的最小示例。这个问题是在代码高尔夫期间出现的,我只是想知道为什么会这样?
    猜你喜欢
    • 1970-01-01
    • 2020-12-02
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    • 2021-01-25
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    相关资源
    最近更新 更多