【发布时间】:2012-05-09 01:33:18
【问题描述】:
如果我理解正确,Clojure 可以返回列表(就像在其他 Lisps 中一样),也可以返回向量和集合。
我真正不明白的是为什么没有总是返回一个集合。
例如,如果我采用以下代码:
(loop [x 128]
(when (> x 1)
(println x)
(recur (/ x 2))))
它确实打印了 128 64 32 16 8 4 2。但这只是因为调用了 println 并且 println 具有打印某些东西的副作用 (?)。
所以我尝试用这个替换它(删除 println):
(loop [x 128]
(when (> x 1)
x
(recur (/ x 2))))
我期待得到一些收集(应该是一个列表),像这样:
(128 64 32 16 8 4 2)
但我得到的是 nil。
我不明白是什么决定了什么可以创建集合,什么不能,以及如何从一个集合切换到另一个集合。另外,看到 Clojure 以某种方式鼓励“函数式”编程方式,您不应该几乎总是返回集合吗?
为什么有这么多显然不返回任何集合的函数?制作这些退货系列的惯用方式是什么?
例如,我将如何通过首先构造一个集合然后以惯用的方式迭代 (?) 来解决上述问题而不是生成的列表/向量?
首先我不知道如何转换 loop 使其产生不同于 nil 的东西,然后我尝试了以下方法:
(reduce println '(1 2 3))
但它打印的是 "1 2nil 3nil" 而不是我期待的 "1 2 3nil"。
我意识到这是基本的东西,但我才刚刚开始,我显然在这里缺少基本的东西。
(P.S.:适当地重新标记,我不知道我应该在这里使用哪些术语)
【问题讨论】:
-
你对
when的理解是错误的,你应该使用if。即使这样,您也会返回x,这是一个数字。实际上,您必须从某个地方创建一个列表才能返回一个。 -
@Seth Carnegie:好的,但是......我的问题是如何确定要创建什么:例如为什么 when 在这里不起作用,我怎么知道?这是否意味着 when 只能在有副作用的函数内部使用?
-
@CedricMartin 函数式编程没有魔法。返回一个数字就是这样做的——返回一个数字,仅此而已。 (在您的情况下,由于该数字返回到不关心返回值的上下文(非尾部位置的
whenbody 子句),因此它会立即被丢弃,因此什么都不会发生。)如果你想要一个集合,你需要明确地创建它。关于when的使用:when正是为了的副作用,所以在学习函数式编程的时候,最好避免。 -
@MatthiasBenkard - 你为什么说'什么时候正好是为了副作用'?它不只是 if 的缩写形式,即。没有 else 子句的 if?
-
@sw1nn 它没有 else 子句,是的,但
if也不需要 else 子句(它是可选的)。when的点是隐含的do,对于无副作用的代码是没有用的。
标签: collections clojure side-effects