Преобразование последовательности операций с картой в простое понимание - PullRequest
2 голосов
/ 30 июля 2011

Я читал в разделе «Программирование в Scala» 23.5, что операции map, flatMap и filter всегда можно преобразовать в «для понимания» и наоборот.

Нам дан следующий эквивалент:

def map[A, B](xs: List[A], f: A => B): List[B] =
  for (x <- xs) yield f(x)

У меня есть значение, рассчитанное по серии операций с картой:

val r = (1 to 100).map{ i => (1 to 100).map{i % _ == 0} }
                  .map{ _.foldLeft(false)(_^_) }
                  .map{ case true => "open"; case _ => "closed" }

Мне интересно, как это будет выглядеть для понимания. Как мне перевести это?

(Если это полезно, на словах это:

  • взять целые числа от 1 до 100
  • для каждого, создать список из 100 логических значений
  • сворачивает каждый список с помощью оператора XOR обратно в логическое значение
  • выдает список из 100 строк "открытый" или "закрытый" в зависимости от логического значения

Я полагаю, что существует стандартный способ перевода операций с картой, и детали реальных функций в них не важны. Хотя я могу ошибаться.)

1 Ответ

6 голосов
/ 30 июля 2011

Является ли это переводом, который вы ищете?

for (i <- 1 to 100;
     val x = (1 to 100).map(i % _ == 0);
     val y = x.foldLeft(false)(_^_);
     val z = y match { case true => "open"; case _ => "closed" })
  yield z

При желании map в определении x также можно перевести как «внутреннее» для понимания..

В ретроспективе, последовательность связанных вызовов map является тривиальной, так как вы можете эквивалентно вызвать map один раз с составными функциями:

 s.map(f).map(g).map(h) == s.map(f andThen g andThen h)

Я нахожу дляПонимание будет более значительным, если речь идет о flatMap и filter.Рассмотрим

for (i <- 1 to 3;
     j <- 1 to 3 if (i + j) % 2 == 0;
     k <- 1 to 3) yield i ^ j ^ k

против

(1 to 3).flatMap { i =>
  (1 to 3).filter(j => (i + j) % 2 == 0).flatMap { j =>
    (1 to 3).map { k => i ^ j ^ k }
  }
}
...