Clojure 使用在另一个方法中定义的方法
我正在研究解决方案,其中指出:Clojure 使用在另一个方法中定义的方法,clojure,Clojure,我正在研究解决方案,其中指出: Write a function which replicates each element of a sequence a variable number of times. 为此,我想: 制作一个方法,该方法需要一个序列和重复每个元素的次数 在此方法中定义一个本地方法,将一个值v,n次复制到一个序列中 考虑到这一点,我编写了以下方法: (fn dupSeqX [aseq x] (fn dupx [v x] (if (= x 1) (list v)
Write a function which replicates each element of a sequence a variable number of times.
为此,我想:
(fn dupSeqX [aseq x]
(fn dupx [v x]
(if (= x 1) (list v) (concat v (dupx v (- x 1))))
)
(reverse (reduce #(concat %1 (dupx %2 x)) '() aseq)))
运行此代码时,出现以下错误:
java.security.PrivilegedActionException: java.lang.Exception: Unable to resolve symbol: dupx in this context (NO_SOURCE_FILE:0)
我如何创建一个本地方法来完成这个koan
有没有一种我不知道的“clojure式”的方法来实现这一点?clojure有很多或真正伟大的功能来帮助你养成“用顺序思考”的习惯。当你发现自己在一个列表中反复写东西时,想想“我可以映射这个吗?”,当你发现自己在列表中做其他事情时,看看这个 在这种情况下,内部函数恰好是内置的,所以您很幸运:)通常您需要自己编写它并将其存储在
let
中,但如果您使其成为一个适当的函数,那么您可能会在代码的其他地方找到它的用途
这里有一个开始的提示
(flatten (map #(repeat 3 %) [1 2 3 4]))
(1 1 1 2 2 2 3 3 3 4 4 4)
ps:
#(重复3%)
是(fn[n](重复3 n))
首先,我们不讨论方法:我们讨论函数。clojure中有些东西可以调用方法,但它与函数不同。如果你停止使用面向对象的行话,你也会失去面向对象的思维方式
你想做的是可能的。您基本上希望在dupseqx
函数中创建一个名为dupx
的新函数。您现在正在做的是创建一个函数,然后将其丢弃(您不会对返回值执行任何操作,只返回函数中的最后一个表单)。由于函数与任何其他值一样,因此可以使用与任何其他值相同的方法:创建局部“变量”。这是什么机制?它是本地绑定,工作原理如下(fn中的名称只是为了让您可以从自身调用它;它不需要与let
绑定的名称相同):
注意,我纠正了其他一些事情
这是一个较短的形式(修复双重名称丑陋):
在“(let[…]”和匹配项之间的所有内容中,现在我们有了一个dupx
函数
现在,剩下的代码可以正常工作了:
(fn dupSeqX [aseq x]
(letfn [(dupx [v x] (if (= x 1) (list v) (cons v (dupx v (dec x)))))]
(reverse (reduce #(concat %1 (dupx %2 x)) '() aseq))))
这段代码可以变得更地道一些:
- 编码准则:命名参数
而不是coll
aseq
- 编码准则:不要使用CAMALCASE这样做
- 当您不需要递归时,它对性能和大数字都是有害的
- 你正在重新发明轮子。这对于学习编码是很好的,但是如果你想了解语言和标准库,就不太好了
coll
是为期望序列的函数命名的标准
(fn [coll times] )
如果你读到这个“序列中的每一个元素”,你的大脑就必须去绘制地图
(fn [coll times]
(map (fn ....) coll))
“复制每个…”基本上是对必须放入映射函数中的内容的描述。我们可以使用repeat
(您的dubx函数,但如果有一些像这样的额外功能,它是懒惰的)
还有一个问题(来自koan)。它希望返回一个seq,而不是每个元素的序列中的一个序列。这就意味着我们必须一起观察结果
(fn [coll times]
(apply concat (map (fn [val] (repeat times val)) coll)))
您经常会看到(apply concat(map…)
模式。标准库中有一个更好的函数,名为mapcat
,我将把内部函数转换成简短的语法
(fn [coll times]
(mapcat #(repeat times %) coll))
希望有帮助 这里有一些提示。我想你指的是函数而不是方法。此外,函数是用defn定义的,而匿名函数(lamdba)是用fn定义的。你把两者混淆了。此外,如果您需要外部函数范围内的局部函数,请使用let或letfn。这是一个非常好的描述,谢谢!感谢您的见解。
(展平(地图…)
->(地图猫…)
(如果某些项目容易展平怎么办?)。祝贺你在10k上成功。:-)是的,(阿瑟地图)。:)展平地图是一个坏习惯
(fn [coll times]
(map (fn [val] (repeat times val)) coll))
(fn [coll times]
(apply concat (map (fn [val] (repeat times val)) coll)))
(fn [coll times]
(mapcat #(repeat times %) coll))