我正在尝试制定一个f(Ys) -> [Y * 2 || Y <- Ys, Y < 4].
的等式。
当我输入列表f([5,1,2,6]).
时,我得到的结果为[2,4]
,而我认为它应该是[10, false]
,它来自f([5,1,2,6]) -> [5 * 2 || 5 <- [1,2,6], 5 < 4]
。
有人能告诉我哪里弄错了,或者可能会通过正确的流程来了解如何实现正确的结果?
答案 0 :(得分:3)
在输入列表元素中,[5,6]
被丢弃,因为Y < 4
为false,留下[1,2]
。
您的输出评估为Y * 2
,因此[2,4]
的结果对我有效。
列表推导采用Ys
的每个值并丢弃谓词不为真的那些(即Y < 4
不为真的那些),然后形成剩余输入列表的列表其中Y成为那些值。结果由Y * 2
转换,因此此时[1,2]
变为[2,4]
。
答案 1 :(得分:3)
列表推导[Y * 2 || Y <- Ys, Y < 4]
直接等同于列表上的过滤器,然后乘法。考虑到你不能乘以 false * 2
,即使这是列表理解中的守卫所意味着的。
过滤器 test 看起来像fun(Y) -> Y < 4 end
,只返回一个布尔值:
-spec my_test(integer()) -> boolean().
my_test(Y) -> Y < 4.
要将它组合成一个返回布尔或整数的函数,你需要一些不同的东西:
-spec multiply_or_false(integer()) -> integer() | false.
multiply_or_false(Y) ->
case Y < 4 of
true -> Y * 2;
false -> false
end.
这是一个比较,然后一个基于结果的分支,它返回false
或整数。
如果你确实想要返回doubleling或boolean,你可以在map或list comprehension中使用像multiply_or_false / 1这样的东西(在这种情况下它们完全相同):
[multiply_or_false(Y) || Y <- Ys].
或
lists:map(fun multiply_or_false/1, Ys).
有时强迫自己将代码中的元素分解为微小的函数并指定它们只是为了澄清你脑海中的真实情况(代码是否最终保持在那种形式)。
答案 2 :(得分:2)
guard
末尾的list comprehension
的返回值Y < 4
,不会包含在您的最终列表中,而是评估为{ {1}}列表中的当前元素将被排除在最终列表中,如果它的计算结果为false
,则该元素将被包含在内。
在您的示例中,因为true
不小于5
,所以它不会包含在4
的最终列表中。