scala - 我可以使用函数组合来避免scala中的“临时列表”吗?
问题描述
在 fpis《function programming in scala》的第 64 页上说
List(1,2,3,4).map(_ + 10).filter(_ % 2 == 0).map(_ * 3)
“每个转换都会产生一个临时列表,该列表只会被用作下一个转换的输入,然后立即被丢弃”
所以编译器或库不能帮助避免这种情况?
如果是这样,这个haskell代码是否也会产生一个临时列表?
map (*2) (map (+1) [1,2,3])
如果是,我可以使用函数组合来避免这种情况吗?
map ((*2).(+1)) [1,2,3]
如果我可以使用函数组合来避免haskell中的临时列表,我可以使用函数组合来避免scala中的临时列表吗?
我知道 scala 使用功能“撰写”来撰写功能:https ://www.geeksforgeeks.org/scala-function-composition/
那么我可以写这个来避免scala中的临时列表吗?
((map(x:Int=>x+10)) compose (filter(x=>x%2==0)) compose (map(x=>x*3)) (List(1,2,3,4))
(IDEA告诉我我不能)
谢谢!
解决方案
编译器不应该这样做。如果您考虑地图融合,它可以很好地与纯函数一起使用:
List(1, 2, 3).map(_ + 1).map(_ * 10)
// can be fused to
List(1, 2, 3).map(x => (x + 1) * 10)
然而,Scala 不是一种纯粹的函数式语言,它也没有任何编译器可以跟踪的纯度概念。例如,由于副作用,行为会有所不同:
List(1, 2, 3).map { i => println(i); i + 1 }.map { i => println(i); i * 10 }
// prints 1, 2, 3, 2, 3, 4
List(1, 2, 3).map { i =>
println(i)
val j = i + 1
println(j)
j * 10
}
// prints 1, 2, 2, 3, 3, 4
另一件需要注意的是,ScalaList
是一个严格的集合——如果你有一个对列表的引用,那么它的所有元素都已经分配在内存中。相反,Haskell 列表是惰性的(就像 Haskell 中的大多数东西一样),所以即使创建了临时的“列表外壳”,它的元素在需要之前都不会被计算。这也允许 Haskell 列表是无限的(你可以写成[1..]
越来越多的数字)
与 Haskell list 最接近的 Scala 对应项是LazyList
,它在请求之前不会评估其元素,然后缓存它们。这样做
LazyList(1,2,3,4).map(_ + 10).filter(_ % 2 == 0).map(_ * 3)
将分配中间LazyList
实例,但在从最终列表中请求它们之前不计算/分配其中的任何元素。LazyList
也适用于无限集合(LazyList.from(1)
类似于上面的 Haskell 示例,除了它是 Int)。
实际上,在这里,map
两次处理副作用或手动融合都没有区别。
您可以通过做将任何集合切换为“惰性” .view
,或者通过做只使用迭代器.iterator
- 它们与任何集合具有大致相同的API,然后通过做返回到具体集合.to(Collection)
,例如:
List(1,2,3,4).view.map(_ + 10).filter(_ % 2 == 0).map(_ * 3).to(List)
将在没有任何中介的情况下制作清单。问题是它不一定更快(尽管通常内存效率更高)。
推荐阅读
- three.js - 用three.js使相对面的交叉边缘平行
- javascript - React 状态只返回一个元素
- algorithm - 找到最大的子矩阵,矩阵中只包含一个零和一
- angular - OneSignal,Ionic 4 - 除非应用重新启动,否则不会调用 getPermissionSubscriptionState()
- javascript - 在 webpack 和 babel 构建的 node_modules 中,console.log 的源映射中断
- onelogin - 启动 OneLogin 示例节点应用程序时出现问题
- python - 打印一行后,时间睡眠不循环工作
- javascript - 查找不包含在另一个对象数组中的数组中的元素
- ruby-on-rails - 验证名称没有制表符或反斜杠 - Rails
- jquery - 包含值时如何在 window.open 中使用 _self?