Recursion Clojure从递归调用返回值
我正在研究Clojure算法来解决这里提出的问题:我遇到了一个小问题 我使用的是递归算法,一开始可能不是正确的选择,遍历一个按最高到最低的值权重比排序的玩偶结构向量。有关守则如下:Recursion Clojure从递归调用返回值,recursion,clojure,Recursion,Clojure,我正在研究Clojure算法来解决这里提出的问题:我遇到了一个小问题 我使用的是递归算法,一开始可能不是正确的选择,遍历一个按最高到最低的值权重比排序的玩偶结构向量。有关守则如下: (defn get-carryable-dolls [dolls carryable-dolls] (def doll (first dolls)) ;initializing for use in multiple places (def rest-dolls (rest dolls)) ;initi
(defn get-carryable-dolls
[dolls carryable-dolls]
(def doll (first dolls)) ;initializing for use in multiple places
(def rest-dolls (rest dolls)) ;initializing for use in multiple places
(
if (will-fit? doll (get-weight-sum carryable-dolls))
( ;will fit
(
if
(= carryable-dolls {})
(def new-doll-set [doll]) ;First trip, get rid of empty set by initializing new
(def new-doll-set (flatten [doll carryable-dolls])) ;otherwise, flatten set into vector of structs
)
;tests to see if we have any more dolls to test, and if so, recurses. Otherwise, should pass the resultant vector
;up the stack. it appears to be the "else" potion of this if statement that is giving me problems.
(if (not= () rest-dolls) (get-carryable-dolls rest-dolls new-doll-set) (vec new-dolls))
)
( ;will not fit
;gets the rest of the dolls, and sends them on without modifying the vector of structs
;it appears to be the "else" potion of this if statement that is giving me problems.
(if (not= () rest-dolls) (get-carryable-dolls rest-dolls carryable-dolls) (vec carryable-dolls))
)
)
)
代码工作正常;可返回的玩偶包含要作为解决方案返回的玩偶结构的所需向量。不幸的是,当我尝试将可返回的玩偶向量返回到调用位置时,我收到以下错误:
CompilerException clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector,compiling:(drugmover\tests.clj:83)
第82-83行改为:
(def empty-dolls {})
(def designated-dolls (get-carryable-dolls sorted-values empty-dolls))
对于编译器错误中可能出现的问题,我感到困惑,因为Clojure似乎更喜欢简洁的错误消息而不是堆栈跟踪,或者至少Clooj中的REPL功能更喜欢简洁的错误消息,所以我不知道如何修复它。如果有人有任何建议,我将不胜感激
提前谢谢
编辑:
我已经用答案和注释中的建议修复修改了代码,并提供了一些注释来帮助说明正在进行的流控制。希望通过说明我的想法,有人能告诉我哪里出了问题。这段代码中有太多的paren,它们导致了问题。我强烈建议您以其他人的方式格式化代码,这将使类似这样的错误很容易突出。我甚至猜不出你想做什么,所以我无法重写整个代码段,但需要注意的是if的语法是:
在这些事情上不允许有额外的参数:例如,如果真的12是可以的,但是如果真的12会尝试将真作为一个函数调用,并且失败,因为它是一个布尔值。如果要将表达式分组并计算其副作用,则需要执行expr1 expr2,而不是expr1 expr2。If代码周围有额外的参数,这就是错误的原因: 以下代码将产生相同的错误,因为当调用else部分创建向量时,它在if中具有相同的额外参数:
((vec {:a 10 :b 100}))
尝试在REPL中执行此操作,您将看到相同的异常:
java.lang.IllegalArgumentException: Wrong number of args (0) passed to: PersistentVector (NO_SOURCE_FILE:0)
以下代码包含了您在其他答案和其他答案中已经收到的大多数建议,即: 去掉多余的和错误的括号 以更惯用的方式格式化代码 对本地名称绑定使用loop/let而不是def 使用seq检查空列表 在添加元素之前,删除对空可携带玩偶序列的不必要检查 如果没有辅助功能(例如will fit?)的定义,我无法对其进行测试,但至少应该解决几个问题,并使代码更具可读性:
(defn get-carryable-dolls
[dolls carryable-dolls]
(loop [doll (first dolls)
rest-dolls (rest dolls)]
(if (will-fit? doll (get-weight-sum carryable-dolls))
(let [new-doll-set (if (seq carryable-dolls)
(cons doll carryable-dolls)
[doll])]
(if (seq rest-dolls)
(recur rest-dolls new-doll-set)
(vec new-dolls)))
(if (seq rest-dolls)
(recur rest-dolls carryable-dolls)
(vec carryable-dolls)))))
以下是对代码的完整重构,它利用了标准的reduce函数并定义了一个函数,该函数提供了核心决策逻辑,无论结果中是否必须包含玩偶:
(defn add-if-fits [dolls doll]
(if (will-fit? doll (get-weighted-sum dolls))
(cons doll carryable-dolls)
carryable-dolls))
(defn get-carryable-dolls [dolls carryable-dolls]
(reduce add-if-fits carryable-dolls dolls))
谢谢你的建议。我将研究减少括号,看看这是否能提供任何提示。这就是在首次使用该语言后24小时内试图解决类似这样的代码问题的危险。因此,如果这已经计算出正确的值,但由于意外地将某个对象作为函数调用而失败,那么您可能可以通过用do a b替换a b的每个实例来修复它。一旦你更加熟悉clojure,你可以返回并删除这个函数中的所有def,这是一个非常命令式风格的保留。我不确定它是否失败,因为它意外地将某个东西作为函数调用。这很可能是因为我在语言交流方面缺乏经验,但老实说,在粘贴的语句中,我看不到一个括号可以删除的例子。你能提供一个更具体的例子吗?例如,从第3行开始的一对括号是多余的。函数体周围没有像大括号一样的括号。@neveu:谢谢你的例子;我已经删除了多余的括号,但不幸的是,它没有解决问题。你在代码中到处撒括号,就像它们是花括号一样。你能提供一个具体的例子,说明我可以删除括号,但仍然得到相同的结果吗?我在这方面非常,非常新。例如:在第一个条件之后,如果有两个圆括号;第一个是不必要的,第二个是正确的,因为它是第二个if的左括号。@Óscar López谢谢,我已经用我所做的更改和一些显示流控制的注释更新了代码,希望能说明我的思维过程。你的if语句周围还有额外的参数。你也不需要第一个,因为一个空序列仍然是一个序列,所以你不需要特别对待它;只需使用conj carryable娃娃即可。如果你真的需要局部变量-和
您不需要它们中的大多数-使用let not def,因为def定义了一个全局变量。skuro,谢谢您的帮助。您的第二个解决方案提供了我正在寻找的解决方案,显然比我最初发布的解决方案简洁得多。你是个救生员!
(defn add-if-fits [dolls doll]
(if (will-fit? doll (get-weighted-sum dolls))
(cons doll carryable-dolls)
carryable-dolls))
(defn get-carryable-dolls [dolls carryable-dolls]
(reduce add-if-fits carryable-dolls dolls))