【发布时间】:2011-11-16 19:27:31
【问题描述】:
为了理解,我不能只写一个打印语句:
def prod (m: Int) = {
for (a <- 2 to m/(2*3);
print (a + " ");
b <- (a+1) to m/a;
c = (a*b)
if (c < m)) yield c
}
但我可以通过虚拟分配轻松绕过它:
def prod (m: Int) = {
for (a <- 2 to m/(2*3);
dummy = print (a + " ");
b <- (a+1) to m/a;
c = (a*b)
if (c < m)) yield c
}
作为一个副作用,并且(到目前为止)仅用于正在开发的代码中,是否有更好的临时解决方案?
除了副作用之外,我不应该使用它有什么严重的问题吗?
更新显示真实代码,其中一种解决方案比预期更难适应:
从与 Rex Kerr 的讨论来看,有必要展示原始代码,这有点复杂,但似乎与问题无关(2x .filter,最后调用一个方法),但是当我尝试将 Rex 的模式应用到它时我失败了,所以我把它贴在这里:
def prod (p: Array[Boolean], max: Int) = {
for (a <- (2 to max/(2*3)).
filter (p);
dummy = print (a + " ");
b <- (((a+1) to max/a).
filter (p));
if (a*b <= max))
yield (em (a, b, max)) }
这是我的尝试——(b * a).filter 是错误的,因为结果是一个 int,而不是一个可过滤的 ints 集合:
// wrong:
def prod (p: Array[Boolean], max: Int) = {
(2 to max/(2*3)).filter (p).flatMap { a =>
print (a + " ")
((a+1) to max/a).filter (p). map { b =>
(b * a).filter (_ <= max).map (em (a, b, max))
}
}
}
第二部分属于 cmets,但无法阅读,如果写在那里 - 也许我最终将其删除。请见谅。
好的 - 这是 Rex 在代码布局中的最后一个答案:
def prod (p: Array[Boolean], max: Int) = {
(2 to max/(2*3)).filter (p).flatMap { a =>
print (a + " ")
((a+1) to max/a).filter (b => p (b)
&& b * a < max).map { b => (m (a, b, max))
}
}
}
【问题讨论】:
-
包含“虚拟”的代码在我的 REPL (scala 2.9.0.1) 中运行。例如,用
prod (20)调用它。 -
在真实的代码示例中,
((a+1) to max/a).filter(b => p(b) && b*a < max).map{ b => em(a,b,max) }可以解决问题。此外,第一张地图应该是 flatMap。 -
非常感谢。部分地,我的错误现在对我来说很明显 - 过滤器
...filter (p)中的布尔数组 p 使表达式中的b消失,而稍后需要它,所以filter (b => p(b))是要走的路。将过滤器与&& b*a < max结合起来也很清楚。然后重复b =>是我如果再搜索 4 个小时就不会找到的东西,而且我想我明天也找不到它,不看这里。 -
如果你真的愿意,你可以第二次调用它
x =>而不是b =>。它只是需要一个名字的东西;它通过过滤器后恰好是同一件事,所以我使用了相同的变量。
标签: scala variable-assignment println for-comprehension