для выражений против foreach в Scala
Я работаю мой путь через программирование в Scala, и хотя я испытываю соблазн взглянуть на вещи с точки зрения Python, я не хочу программировать "Python в Scala."
Я не совсем уверен, что делать, насколько поток управления идет: в Python, мы используем for x in some_iterable
до смерти, и мы любим его. Очень похожая конструкция существует в Scala, которую Одерский называет a для выражение, вероятно, чтобы отличить его от цикла Java for. Кроме того, у Scala есть foreach
атрибут (я думаю, это будет атрибут, я не знаю достаточно о Scala, чтобы правильно назвать его) для итерационных типов данных. Не похоже, что я могу использовать foreach
сделать гораздо больше, чем вызов одной функции для каждого элемента в контейнере, хотя.
это оставляет мне несколько вопросов. Во-первых, для выражений важны/сильно используются конструкции в Scala, как в Python, а во-вторых, когда я должен использовать foreach
вместо выражения for (кроме очевидного случая вызова функция на каждом элементе контейнера)?
Я надеюсь, что я не буду ужасно двусмысленным или чрезмерным, но я просто пытаюсь Грок некоторые основы дизайна/языка в Scala (который кажется очень крутым до сих пор).
5 ответов:
python использует
for
в списке понимания и генератор выражений. Это очень похоже на scalafor
выражение:это в Python
>>> letters = ['a', 'b', 'c', 'd'] >>> ints = [0, 1, 2, 3] >>> [l + str(i) for l in letters for i in ints if i % 2 == 0] ['a0', 'a2', 'b0', 'b2', 'c0', 'c2', 'd0', 'd2']
это скала
scala> val letters = List('a', 'b', 'c', 'd') scala> val ints = List(0, 1, 2, 3) scala> for (l <- letters; i <- ints if i % 2 == 0) yield l.toString + i res0: List[java.lang.String] = List(a0, a2, b0, b2, c0, c2, d0, d2)
каждая конструкция может принимать несколько генераторов / итераторов, применять выражения фильтров и давать комбинированное выражение. В python the
(expr for v1 in gen1 if expr1 for v2 in gen2 if expr2)
примерно эквивалентно:for v1 in gen1: if expr1: for v2 in gen2: if expr2: yield expr
In скала
for (v1 <- gen1 if expr1; v2 <- gen2 if expr2) yield expr
примерно эквивалентно:gen1.withFilter(expr1).flatMap(v1 => gen2.withFilter(expr2).map(v2 => expr))
если вы любите питон
for x in xs
синтаксис, вы, вероятно, любите scalafor
выражение.Scala имеет некоторые дополнительные синтаксические и переводческие повороты. Синтаксис мудрый
for
может использоваться с фигурными скобками, так что вы можете поместить операторы на отдельных строках. Вы также можете выполнять назначения значений.val res = for { i <- 1 to 20; i2 = i*i j <- 1 to 20; j2 = j*j k <- 1 to 20; k2 = k*k if i2 + j2 == k2 } yield (i, j, k)
и
v1 <- gen1
действительно выполняет матчcase v1 => gen1
. Если эти элементы игнорируются из итерации.scala> val list = List(Some(1), None, Some(2)) scala> for (Some(i) <- list) yield i res2: List[Int] = List(1, 2)
я думаю
for
занимает важное место в языке. Я могу сказать, что в книге, которую Вы читаете, есть целая глава (23) об этом!
да, Scala для понимания (как они обычно известны) используются много, но на самом деле они просто синтаксический сахар для определенной комбинации методов, и многие предпочитают называть эти методы непосредственно вместо использования синтаксического сахара.
чтобы лучше понять Scala для понимания, пожалуйста, обратитесь к этот вопрос. В частности, вы увидите, что
for (x <- xs) f(x)
Это то же самое какxs.foreach(x => f(x))
.теперь, вы упомянули, что вы не кажетесь много пользы с
foreach
метод, но я отмечу, что почти все методы коллекций Scala реализованы (или могут быть реализованы) только с помощьюforeach
. Смотрите документацию дляTraversable
-- все его методы могут быть реализованы толькоforeach
.обратите внимание, что в Scala
yield
не имеет никакого сходства с питономyield
-- вы можете посмотреть это тоже вопрос.
С его поддержкой вложенных итераций, фильтров и преобразований, я бы сказал, что Scala
for
одна из сильных сторон языка и очень центральный. Я склонен отдавать предпочтение его использованиюforeach
,map
иfilter
.
командлет foreach-это функциональный стиль, в то время как для императивном стиле. Если вы когда-либо делали Лисп или схему, вы уже знакомы с функциональным программированием. Если у вас нет, то это может быть немного запутанным на первый. Первое, что я бы сделал, это прочитать синтаксис закрытия, который является анонимными функциями, которые вы передаете в такие вещи, как foreach. Как только вы поймете, что все это будет иметь больше смысла.