在Scala中管理灵活的,类型化的,不可变的数据结构的正确方法是什么? [英] What is a proper way to manage flexible, typed, immutable data structures in Scala?
问题描述
抽象类Record {
//必填字段
val productCode:选项[字符串]
val价格:选项[双]
//可选字段
val备注:选项[字符串] =无
使用的val: Option [Boolean] = Option(false)
}
然后创建它们:
val r =新记录{
覆盖val productCode =选项(abc)
覆盖val价格=选项(32.12)
}
有几点需要注意:
- 我对非可选字段使用Option,因此
a。我不必记住哪些字段是可选的
b。我可以在不更改界面的情况下更改哪些字段是可选的。 - Option选项会增加很多噪音。我非常喜欢那样的游戏,但我也不想使用空值。在使用结构时考虑所有对getOrElse的调用时尤其如此。 (我敢打赌,这种语言有一个聪明的方法来声明自动复制这些)。
-
这使得批量赋值(我所做的是因为我有一个字段数组)很困难一个子类将新字段混合在一起,例如:
override val List(productCode,price,discount)= fields // fields is a List
$ b不会编译,因为
折扣
没有在超类中定义,因此没有覆盖。我不确定是否有办法做到这一点。
我的主要问题是:
- 是否有更好的整体方法来管理不可变数据结构?
- 是否有直接的方法来复制记录并只更改一个值而无需编写样板代码? li>
例如(伪代码):
val r2 = r.clone {覆盖val used = true}
$ c $我已经听说2.8为case类引入了类似的东西,但是在鼓励不可变数据结构的语言中,我很惊讶地发现这在2.8之前并不容易,我仍然在2.7。解决方案这看起来是2.8中非常重要的一个问题:
case class Employee(name:String,age:Int)
val joe = Employee( Joe,25)
val bob = joe copy(name =Bob)
将这个与默认值相结合,你给的例子可以很容易地重写为一个case类,我认为这是实现不可变数据类型的'正确'方法(我不确定scala是否是这样,但是来自ocaml / haskell,看起来不错)。
在2.7中,你将不得不实现一大堆helper函数:
def asUsed(r:Record):Record = {
Record(r.productCode,r.price,r.nodes,Some(true))
}
Yuck。他们应该真的快点2.8 ...
Right now I have classes like:
abstract class Record { // Required fields val productCode:Option[String] val price:Option[Double] // Optional fields val notes:Option[String] = None val used:Option[Boolean] = Option(false) }
Then create them:
val r = new Record { override val productCode = Option("abc") override val price = Option(32.12) }
A few things to note:
- I use Option for the un-optional fields so that a. I don't have to remember which fields are optional b. I can change which fields are optional without changing my interface
- The Option stuff adds a lot of noise. I'd love for that not to be there, but I also don't want to use nulls. This is particularly true when taking into account all the calls to getOrElse when I'm using the structure. (I bet there's a clever way for the language to declaratively autobox these.)
This makes mass assignment (which I'm doing because I have an array of fields) difficult if a subclass mixes new fields in, e.g.:
override val List(productCode, price, discount) = fields // fields is a List
will not compile because
discount
is not defined in the superclass and therefor not an override. I'm not sure if there is a way to do this.My main question is:
- Is there a better overall way to manage immutable data structures?
- Is there a straightforward way to copy a record and change just one value without writing boilerplate code?
e.g. (pseudocode}:
val r2 = r.clone { override val used = true }
I have heard 2.8 introduces something like this for case classes, however in a language that encourages immutable data structures, I'd be surprised to find out this is not easier before 2.8. I'm still in 2.7.
解决方案This looks to be a problem very much addressed in 2.8:
case class Employee(name: String, age: Int) val joe = Employee("Joe", 25) val bob = joe copy (name = "Bob")
Combine this with default values, and the example you give can be easily rewritten as a case class, which I think of as the 'proper' way to implement an immutable data type. (I'm not sure if that's true for scala, but coming from ocaml/haskell, it seems right.)
In 2.7 you're going to have to implement a whole lot of helper functions:
def asUsed(r: Record): Record = { Record(r.productCode, r.price, r.nodes, Some(true)) }
Yuck. They should really hurry along 2.8...
这篇关于在Scala中管理灵活的,类型化的,不可变的数据结构的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- 是否有更好的整体方法来管理不可变数据结构?