для выражений против foreach в Scala - PullRequest
54 голосов
/ 17 декабря 2010

Я пробираюсь через Программирование в Scala , и, хотя я испытываю желание посмотреть на вещи с точки зрения Python, я не хочу программировать "Python in Scala".

Я не совсем уверен, что делать с потоком управления: в Python мы используем for x in some_iterable до смерти, и нам это нравится. В Scala существует очень похожая конструкция, которую Одерский называет выражением для , вероятно, чтобы отличить ее от цикла for для Java. Кроме того, у Scala есть атрибут foreach (я думаю, это будет атрибут, я не знаю достаточно о Scala, чтобы правильно назвать его) для итеративных типов данных. Похоже, я не могу использовать foreach для выполнения гораздо большего, чем вызов одной функции для каждого элемента в контейнере.

Это оставляет меня с несколькими вопросами. Во-первых, для выражений важные / часто используемые конструкции в Scala, как в Python, и, во-вторых, когда я должен использовать foreach вместо выражения for (кроме очевидного случая вызова функции для каждого элемента контейнера)

Надеюсь, я не слишком двусмысленна и не слишком заурядна, но я просто пытаюсь ухватиться за некоторые основы дизайна / языка в Scala (которые пока кажутся очень крутыми).

Ответы [ 5 ]

59 голосов
/ 17 декабря 2010

python использует for в списках и выражениях генератора.Они очень похожи на выражение scala for:

это 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

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 (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

В Scala for (v1 <- gen1 if expr1; v2 <- gen2 if expr2) yield expr примерно соответствует:

gen1.withFilter(expr1).flatMap(v1 => gen2.withFilter(expr2).map(v2 => expr))

Если вам нравится синтаксис Python for x in xs, выСкорее всего, вам понравится выражение scala for.

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)!

25 голосов
/ 17 декабря 2010

Да, Scala для понимания (как их обычно называют) часто используется, но на самом деле они просто синтаксический сахар для определенной комбинации методов, и многие предпочитают вызывать эти методы напрямую, а не использовать синтаксический сахар.

Чтобы лучше понять Scala для понимания, обратитесь к этому вопросу .В частности, вы увидите, что for (x <- xs) f(x) - это то же самое, что и xs.foreach(x => f(x)).

. Теперь вы упомянули, что вам не очень подходит метод foreach, но я укажучто почти все методы коллекций Scala (или могут быть) реализованы с помощью foreach.См. Документацию для Traversable - все ее методы могут быть реализованы только с foreach.

Обратите внимание, что yield в Scala не похож на Python yield - вы можете посмотреть , что вопрос тоже.

3 голосов
/ 17 декабря 2010

foreach - это функциональный стиль, а for - императивный стиль. Если вы когда-либо делали какие-то шутки или схемы, вы уже знакомы с функциональным программированием. Если у вас нет, то сначала это может быть немного запутанным. Первое, что я хотел бы сделать, это прочитать синтаксис замыкания, являющийся анонимными функциями, которые вы передаете в такие вещи, как foreach Как только вы поймете, что все это будет иметь больше смысла.

3 голосов
/ 17 декабря 2010

На ваши вопросы в основном отвечают следующие вопросы:

Для Scala's For Conpretions

Scala Yield

Подводя итог:Это в значительной степени стилистическое.Лично я предпочитаю функциональную методологию, но предпочитаю краткость пониманий при работе с вложенными циклами.

3 голосов
/ 17 декабря 2010

С его поддержкой вложенных итераций, фильтров и преобразований, я бы сказал, что Scala for является одной из сильных сторон языка и очень важна. Я склоняюсь к тому, чтобы использовать foreach, map и filter.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...