scala 中的 println 用于理解
在 for 理解中,我不能只放置一条 print 语句:
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))
}
}
}
第二部分属于评论,但无法阅读,如果写在那里 - 也许我最终会删除它。请原谅。
好的 - 这是 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))
}
}
}
In a for-comprehension, I can't just put a print statement:
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
}
but I can circumvent it easily with a dummy assignment:
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
}
Being a side effect, and only used (so far) in code under development, is there a better ad hoc solution?
Is there a serious problem why I shouldn't use it, beside being a side effect?
update showing the real code, where adapting one solution is harder than expected:
From the discussion with Rex Kerr, the necessity has risen to show the original code, which is a bit more complicated, but did not seem to be relevant for the question (2x .filter, calling a method in the end), but when I tried to apply Rex' pattern to it I failed, so I post it here:
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)) }
Here is my attempt -- (b * a).filter is wrong, because the result is an int, not a filterable collection of 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))
}
}
}
Part II belongs to the comments, but can't be read, if written there - maybe I delete it in the end. Please excuse.
Ok - here is Rex last answer in code layout:
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))
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这就是你需要写的方式:
This is how you need to write it:
从 Scala 2.13 开始,链接操作
tap
,已包含在标准库中,可以在任何地方以最小的侵入性使用我们需要打印管道的一些中间状态:tap
链接操作会产生副作用(在本例中为println
)一个值(在本例中a
),同时返回值 (a
) 不变:调试时非常方便,无需修改代码即可使用一堆
tap
:Starting
Scala 2.13
, the chaining operationtap
, has been included in the standard library, and can be used with minimum intrusiveness wherever we need to print some intermediate state of a pipeline:The
tap
chaining operation applies a side effect (in this caseprintln
) on a value (in this casea
) while returning the value (a
) untouched:It's very convenient when debugging as you can use a bunch of
tap
s without having to modify the code:我通常发现这种编码风格相当难以遵循,因为循环和中间结果等都相互混合在一起。我会编写类似这样的内容,而不是 for 循环
。这也使得添加打印语句等变得更容易。
I generally find that style of coding rather difficult to follow, since loops and intermediate results and such get all mixed in with each other. I would, instead of a for loop, write something like
This also makes adding print statements and such easier.
将副作用语句放在 for 理解中(或者实际上放在任何函数的中间)似乎不是一个好的风格,除了调试之外,在这种情况下,你叫它什么并不重要(“debug “看起来是个好名字)。
如果你真的需要,我认为你最好通过分配一个中间值来更好地分离你的关注点,例如(你原来的布局更漂亮):
变成
It doesn't seem like good style to put a side-effecting statement within a for-comprehension (or indeed in the middle of any function), execept for debugging in which case it doesn't really matter what you call it ("debug" seems like a good name).
If you really need to, I think you'd be better separating your concerns somewhat by assigning an intermediate val, e.g. (your original laid out more nicely):
becomes