【问题标题】:Avoiding the use of global vars in this situation在这种情况下避免使用全局变量
【发布时间】:2017-04-27 13:36:24
【问题描述】:

我写了这个“代码”来说明问题,因为实际代码很大

(defn add-list
  ([number]

  (def used [number])
  (add-list number used))

  ([number used]

   ;Add elements to used
   ;Process the elements in used
   ;Find the next number

   (add-list number used)
   ))

我需要一个可以在 fn 中访问的向量,这将允许我处理向量内的项目,然后将输出添加到向量中,以便旧项目和新项目都在这个向量中下一个周期。

我通过在 add-list 函数上方定义向量来使其工作,但是如果我第二次在 repl 上运行程序,向量不会被清除。它还说向量有时是未绑定的。

【问题讨论】:

  • 您需要更具体地了解代码需要做什么。您可能还希望查看用于累积结果的reduce 函数:clojuredocs.org/clojure.core/reduce
  • 我没有添加数字,我只是想将一个元素向量传递到这个循环中,该循环将根据当前内容添加到向量中。
  • 我一直在使用上述样式使其工作不可靠,但出现以下错误:IllegalArgumentException 不知道如何从以下位置创建 ISeq:clojure.lang.Var$Unbound
  • 代码错误。 (add-list 3) 产生 StackOverflowError,因为 arity-2 函数实际上是 (defn add-list [number used] (add-list number used)),这是一个不可避免的递归。

标签: clojure tail-recursion


【解决方案1】:

reduce 函数可用于累积结果列表,而不仅仅是求和值:

(defn accum-reverse
  [cum-state curr-val]
  (cons curr-val cum-state))

(println
  (reduce accum-reverse
    []              ; initial value of cum-state
    [1 2 3 4 5]     ; fed into curr-val one at a time
  ))

;=> (5 4 3 2 1)

函数accum-reverse被调用了5次。第一次cum-state[]的初始值,空向量。每次后续时间cum-state 都设置为上一个来自accum-reverse 的返回值。

除了在线文档,您还可以从Clojure for the Brave & True 获得一些有用的信息。大部分是在线的,但也值得购买。

【讨论】:

  • 谢谢。我目前遇到的问题是我正在尝试从循环中更新向量中的数据,但循环并没有获取更新的数据,而只是获取后续周期中的初始数据。我知道我正在正确更新它,向量是在循环之外定义的
  • 我似乎无法找到为每个递归循环提供最新数据的方法
  • 也许值得注意的是accum-reverse很像conj,如果你使用()作为你的初始值而不是[]
  • @MDubzem,正如 Alan 所指出的,每次您在 accum-reverse 函数中时,该函数的第一个参数是 cum-state,它包含每次迭代产生的所有值。所以在上面的例子中,经过 2 次迭代,cum-state 将有[5 4]。那是新的价值清单。如果你想同时拥有旧的和新的,你有两个选择:1) 获取reduce 的结果并将旧值放在一个新的数据结构中,或者 2) 使用 old 和 will be new 创建混合结构结构作为 reduce 的初始值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-06
  • 1970-01-01
  • 2021-05-04
相关资源
最近更新 更多