加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 避免在函数式编程中重新分配 – 不好的例子?

发布时间:2020-12-16 10:08:25 所属栏目:安全 来源:网络整理
导读:在许多网络文章中,函数式编程被表示为避免各种变量重新分配,因此仅推广“最终”变量,至少为了更好的阅读. 它们中的大多数都采用带有计数器变量递增的不良循环的样本. (比如着名的i或x = x 1. 这里有一篇鲍勃叔叔的文章说明:FP Episode 1 因此,这些文章表明,
在许多网络文章中,函数式编程被表示为避免各种变量重新分配,因此仅推广“最终”变量,至少为了更好的阅读.

它们中的大多数都采用带有计数器变量递增的不良循环的样本. (比如着名的i或x = x 1.
这里有一篇鲍勃叔叔的文章说明:FP Episode 1

因此,这些文章表明,依靠可变变量经常导致副作用,特别是防止我们所谓的“参照透明度”,因此,更难以构建在多线程或更好的多处理器上运行的程序.

我的问题是:众所周知,我通常是一个线程LOCAL变量,因此即使并发处理也不会出现问题.

为什么选择一个像带有局部变量的循环这样的例子作为赋值的缺点,并且允许直接得出结论并发编程存在风险?这两件事与我严格无关.

为了更清楚,为什么不选择全局变量(或字段对象)的重新分配,这显然是并发编程的敌人,而不像Java那样过度使用所有的锁定模板.

我真的认为这个循环示例并不是将函数式编程的好处传递给命令式程序员的最好例证.

此外,它导致与“noob”函数程序员混淆,因为Scala例如在List.scala类中使用了很多while循环模式:

override def take(n: Int): List[A] = {
    val b = new ListBuffer[A]
    var i = 0
    var these = this
    while (!these.isEmpty && i < n) {  
      i += 1   // reassignment here
      b += these.head
      these = these.tail
    }
    if (these.isEmpty) this
    else b.toList
  }

解决方法

我认为Odersky自己说他们的目标是使API能够正常运行,但内部代码是特定实现的最佳选择.因此,您可能不应该搜索Scala库内部以“充分利用Scala”或“FP的优秀示例”.

使用可变状态来保存索引(例如)也非常容易出错.因此,您应该将操作用于整个集合(filter / map / flatMap等),这样您就不必担心“索引越界”等问题.尽管如此,这些操作通常会导致大量的临时/中间集合被创建,因此它们会导致额外的垃圾收集.这通常对99%的程序无关紧要,但同样,这些程序在Scala库内部尽可能优化.

所以,是的,除了实现“生存”以及尽可能少的可变状态之外,还有一个地方可用于单线程程序,因为错误的可能性较小,可测试性更强,可读性更好.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读