将一系列地图操作转换为for-comprehension

Lui*_*hys 2 functional-programming scala for-comprehension

我在Scala编程第23.5节中读到,map,flatMap和filter操作总是可以转换为for-comprehensions,反之亦然.

我们给出了以下等价物:

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

我有一系列地图操作计算的值:

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

我想知道这对于理解是什么样的.我该如何翻译?

(如果它有用,用这个词来说就是:

  • 取整数从1到100
  • 对于每个,创建一个包含100个布尔值的列表
  • 使用XOR运算符折叠每个列表,返回布尔值
  • 根据布尔值产生100个字符串"打开"或"关闭"的列表

我想有一种标准的方法来转换地图操作,其中的实际功能的细节并不重要.我可能是错的.)

Kip*_*ros 6

这是你正在寻找的那种翻译吗?

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
Run Code Online (Sandbox Code Playgroud)

如果需要,map定义中的内容x也可以翻译成"内在的"理解.

回想起来,一系列链式map调用有点微不足道,因为你可以map用组合函数等效调用一次:

 s.map(f).map(g).map(h) == s.map(f andThen g andThen h)
Run Code Online (Sandbox Code Playgroud)

我发现,当涉及flatMap并且filter参与时,理解能够成为更大的胜利.考虑

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

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