Подтвердить что ты не робот

Для выражений в сравнении с foreach в Scala

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

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

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

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

4b9b3361

Ответ 1

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 имеет некоторые дополнительные синтаксические и трансляционные твисты. Синтаксис wise 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)!

Ответ 2

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

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

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

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

Scala Для понимания

Scala Доходность

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