def foo(l: List[Int]) =
List(1,2,3)
.map(_ + 1) // A
.map(x => {println(x);x}) // B
.map(_ + 2) // C
.map(x => {println(x);x}) // D
.map(_ + 3)
目的是在步骤A
和C
之后打印或登录文件,这是其中一个实现。这是一个好习惯吗?
或者将其分解为多个临时变量,
def foo(l: List[Int]) = {
val nums = List(1,2,3).map(_ + 1)
nums.foreach(println)
val nums2 = nums.map(_ + 2)
nums2.foreach(println)
nums2.map(_ + 3)
}
有没有更好或更直接的方式?感谢
让我进一步澄清我的意图。我的想法是将副作用println(...)
移出map(...)
函数,但我想在此过程中打印结果。我认为不需要优化第B
行和D
。
答案 0 :(得分:1)
一种方法是创建一个继承自List类的类,并覆盖.map
方法。
问题是List无法在密封时继承。
因此,解决方案是将列表包装在新类中并编写.map
方法,该方法将调用原始List.map
并打印每个映射元素的映射结果:
class PrintList[T](l: List[T]) {
def map[B](f: T => B): PrintList[B] = {
new PrintList[B](l.map { e =>
val v = f(e); println(v); v
})
}
def toList(): List[T] = l
override def toString(): String = "Print" + l.toString
}
以这种方式应用:
new PrintList(List(1, 2, 3)).map(_ + 1).map(_ + 2)
打印:
2
3
4
4
5
6
并返回:
println(new PrintList(List(1, 2, 3)).map(_ + 1).map(_ + 2))
> PrintList(4, 5, 6)
println(new PrintList(List(1, 2, 3)).map(_ + 1).map(_ + 2).toList)
> List(4, 5, 6)
答案 1 :(得分:0)
也许你重构函数+记录到一个新函数:
def loggedFun (x: Int)(f: Int => Int) : Int = { val y = f(x); println (y); y }
可以像这样使用:
List(1,2,3).map(loggedFun (_)(_ + 1)).map(loggedFun (_)(_ + 2)).map(_ + 3)
并进一步推广出类型(Int→A)。
def loggedFun[A] (x: A)(f: A => A) : A = { val y = f(x); println (y); y }
我很确定,类别理论中有从A到A的这类函数的名称,但我不知道哪个;对不起。
答案 2 :(得分:0)
对这个微不足道的问题的非平凡回答是作家monad。这个模式的一个很好的例子是http://blog.tmorris.net/posts/the-writer-monad-using-scala-example/