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

替代在构造函数中执行大量计算 – scala

发布时间:2020-12-16 19:16:51 所属栏目:安全 来源:网络整理
导读:我正在学习一个新项目的 scala,尽可能地追求不变性和功能风格. 我正在创建的对象之一在其构造函数中接受了大量输入,然后重复应用大量计算来生成相关输出,这些输出作为字段存储在对象上. 在执行计算并将其结果内部添加到可变ListBuffer时,关于该对象的所有其
我正在学习一个新项目的 scala,尽可能地追求不变性和功能风格.

我正在创建的对象之一在其构造函数中接受了大量输入,然后重复应用大量计算来生成相关输出,这些输出作为字段存储在对象上.

在执行计算并将其结果内部添加到可变ListBuffer时,关于该对象的所有其他内容都是不可变的 – 一旦创建,您就无法更改任何输入值并再次运行计算显然会产生相同的结果.

但是,在构造函数中进行如此多的计算似乎并不合适.我能看到的唯一方法是将计算值设置为变量并提供执行计算的run方法 – 但是这个方法可以被多次调用,这是毫无意义的.

在scala构造函数中做很多事情真的很好吗?例如,没有对DB的调用,只是内部计算.或者有一些模式吗?

这是非常简单形式的基本思想:

class Foo(val x:Int,val y:Int,calculations:List[Calculation]) {
  val xHistory = new collection.mutable.ListBuffer[Int]()
  val yHistory = new collection.mutable.ListBuffer[Int]()

  calculations.map { calc => calc.perform(this) }.foreach { result => 
    xHistory += result.x 
    yHistory += result.y
  }
}

基本上我希望输入包装在一个方便的Foo对象实例中,这样我就可以将它传递给各种计算策略(每个计算策略可能需要不同的输入组合).

解决方法

在构造函数内部工作

通常我在构造函数中做昂贵的东西.但请注意,评论中提到构造函数代码可能不太优化(在此处插入Java实现,这是正确的).如果您有多线程应用程序,也请阅读下一段.

延迟初始化

我不知道在构造函数中做大量工作可能有什么问题.

正如评论中所指出的,构造函数内部运行的代码可能存在问题.因此,Scala 2.8.0中引入了DelayedInit特性.例如,在使用Swing GUI元素时会出现此类问题.

The DelayedInit trait provides another tool to customize
initialization sequences of classes and objects. If a class or object
inherits from this trait,all its initialization code is packed in a
closure and forwarded as an argument to a method named delayedInit
which is defined as an abstract method in trait DelayedInit.

Implementations of delayedInit have thus full freedom when to execute
the initialization code. For instance,Scala’s new App trait stores
all initialization sequences in an internal buffer and executes them
when the object’s main method is called.

懒惰的构造

要以不同的方式延迟计算,可以使用以下方法,这也解决了并发问题:

>您可以使用lazy val成员,这些成员将在首次请求时进行计算.
>如果计算一系列昂贵的对象,您可能希望使用像Stream这样的“惰性”数据结构.这就像一个List,只按需计算下一个元素.因此,在某个时间点,仅计算了已经访问过的流的初始部分.

指示使用懒惰

您可能想要做的另一个考虑因素是计算值是否会被使用.如果可能不需要它们,那么使用我描述的惰性方法就是要走的路.另一方面,如果你肯定访问这些昂贵的成员,我认为在构造函数中进行计算没有任何问题,并且使用惰性成员可能会增加不必要的计算开销.

关于OP示例的注释

在构造函数中做危险的事情并不好;比如让对部分构造的对象的引用转义构造函数(通过this-reference). OP中的示例使用calc.perform(this)执行此操作.以下建议无法修复此“潜在错误”.

(编辑:李大同)

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

    推荐文章
      热点阅读