【问题标题】:How can I collect several items for every iteration of a recursive function如何为递归函数的每次迭代收集多个项目
【发布时间】:2013-01-31 00:38:58
【问题描述】:

我想为每次调用递归函数创建几个项目,并将所有内容收集到一个列表中。也就是说,我想做这样的事情:

(defn myfunc [x]
  (loop [x x retur '()]
    (when condition1
      (let [templist '()]
        (if condition2 (def templist (conj templist {:somekey someval})))
        (if condition3 (def templist (conj templist {:somekey someval})))
        (recur (+ x 1) (concat retur templist))))))

问题是在 Clojure 中我无法重新绑定 let。我想避免使用全局变量。

【问题讨论】:

    标签: recursion clojure lisp


    【解决方案1】:

    核心中的一些函数使用这种通过let 链接相同符号的模式来有条件地建立一个值。我必须将 contition1 更改为不会永远循环的示例,并将 when 更改为 if,以便它可以在循环结束时返回一个值。

    (defn myfunc [x someval1 someval2 condition1 condition2 condition3]
      (loop [x x retur '()]
        (if (condition1 x)
          (let [templist '()
                templist (if condition2 (conj templist {:somekey1 someval1}) templist)
                templist (if condition3 (conj templist {:somekey2 someval2}) templist)]
            (recur (+ x 1) (concat retur templist)))
          retur)))
    

    然后可以测试:

     user> (myfunc 0 1 2 #(< % 5) true true)
     ({:somekey2 2} {:somekey1 1} {:somekey2 2} {:somekey1 1} {:somekey2 2} 
      {:somekey1 1} {:somekey2 2} {:somekey1 1} {:somekey2 2} {:somekey1 1})
    
    user> (myfunc 0 1 2 #(< % 5) true false)
    ({:somekey1 1} {:somekey1 1} {:somekey1 1} {:somekey1 1} {:somekey1 1})
    

    let 的想法是,如果条件为真,则让每个阶段更改值,如果条件为假,则将其原样返回。这种模式使函数式代码具有命令式外观,有助于清楚地说明值是如何构造的,尽管在使用它将命令式逻辑“转换”为函数式程序时也可能太过分了。

    【讨论】:

      【解决方案2】:

      每当我需要执行一些面向步骤的操作时,我更喜欢使用线程宏-&gt;。

      (defn myfunc [x]
        (loop [x x retur '()]
          (when condition1
              (let [r (-> '()
                          (#(if condition2 (conj % {:somekey 1}) %))
                          (#(if condition3 (conj % {:somekey 2}) %)))]
              (recur (+ x 1) (concat retur r))))))
      

      【讨论】:

      • myfunc 的结果将始终为nil。我猜when 在这里不合适。
      • 只要在不满足条件1时将其切换为返回retur的if
      • 是的,我只是使用了与问题相同的结构,因为问题是关于更新值
      【解决方案3】:

      您尝试使用通过分配链获取结果的命令式模式。取而代之的是,您可以尝试以更具声明性的方式解决您的问题,这对于作为函数式语言的 clojure 来说更为惯用。例如

      (defn myfunc [x]
        (loop [x x retur '()]
          (if condition1
            (recur (inc x) (concat retur
                                   (when condition2 [{:somekey1 someval1}])
                                   (when condition3 [{:somekey2 someval2}])))
            retur)))
      

      【讨论】:

      • 我猜在这个问题中 2 if 是独立的,而 cond 会将它们组合起来并选择第一个条件为真
      猜你喜欢
      • 2015-08-16
      • 2015-07-11
      • 2023-01-17
      • 1970-01-01
      • 1970-01-01
      • 2021-12-09
      • 2022-06-28
      • 2013-09-10
      • 2021-09-15
      相关资源
      最近更新 更多