Println в scala для понимания
В понимании я не могу просто поставить оператор печати:
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
}
Будучи побочным эффектом и используется только (пока) в разрабатываемом коде, есть ли лучшее решение ad hoc?
Есть ли серьезная проблема, почему я не должен ее использовать, помимо побочного эффекта?
обновление реального кода, где адаптация одного решения сложнее, чем ожидалось:
Из обсуждения с Рексом Керром возникла необходимость показать исходный код, который немного сложнее, но, похоже, не был релевантен для вопроса (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))
}
}
}
Часть II относится к комментариям, но не может быть прочитана, если она написана - возможно, я удалю ее в конце. Извините.
Хорошо - вот последний ответ Рекса в макете кода:
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))
}
}
}
Ответы
Ответ 1
Вот как вам нужно его написать:
scala> 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
| }
prod: (m: Int)scala.collection.immutable.IndexedSeq[Int]
scala> prod(20)
2 3 res159: scala.collection.immutable.IndexedSeq[Int] = Vector(6, 8, 10, 12, 14
, 16, 18, 12, 15, 18)
Ответ 2
Я обычно считаю, что стиль кодирования довольно сложно выполнить, поскольку петли и промежуточные результаты и все они смешиваются друг с другом. Я бы вместо цикла for написал что-то вроде
def prod(m: Int) = {
(2 to m/(2*3)).flatMap { a =>
print(a + " ")
((a+1) to m/a).map(_ * a).filter(_ < m)
}
}
Это также упрощает добавление инструкций печати.
Ответ 3
Не похоже на хороший стиль, чтобы поставить побочный эффект в рамках понимания (или даже в середине любой функции), execept для отладки, и в этом случае на самом деле не имеет значения, что вы называете ( "debug" кажется хорошим именем).
Если вам действительно нужно, я думаю, что вам лучше отделить свои проблемы, назначив промежуточный вал, например. (ваш оригинал выложен более красиво):
def prod (p: Array[Boolean], max: Int) = {
for {
a <- (2 to max / (2 * 3)) filter p
debug = print (a + " ")
b <- ((a + 1) to max / a) filter p
if a * b <= max
} yield em(a, b, max)
}
становится
def prod2 (p: Array[Boolean], max: Int) = {
val as = (2 to max / (2 * 3)) filter p
for(a <- as) print(a + " ")
as flatMap {a =>
for {
b <- ((a + 1) to max / a) filter p
if a * b <= max
} yield em(a, b, max)
}
}