Managing flexible, typed, immutable data structures in Scala in 2.8.x
This is a follow-up now that Scala 2.8.0 be开发者_运维知识库ta is out to this question:
What is a proper way to manage flexible, typed, immutable data structures in Scala?
The new technique is to copy a case class, e.g.
case class Person(name:String, email:String)
val bob = Person("Bob", "bob@z.com")
val jill = bob.copy(name = "Jill")
This works great, except for the fact that Scala seems to limit me to 22 (?) properties in a case class. That might seem like a lot, it's insufficient in my case.
With 23, I get: "error: type Function23 is not a member of package scala". I could possibly define my own Function23, etc., but I don't know the implications of that.
So now I'm back to square one. I need to use public vars, which I'm trying to avoid, or create a 26+ parameter constructor and a paired copy method. Ick.
22 seems like a rather arbitrary limit here. Is there a way around this?
This is for data import, which looks something like this:
new CatalogImportRecord() {
override val List(SVal(vendorSku), SVal(title), IVal(issues),
_, // YToMVal(termMonths),
DVal(sellPrice), DVal(buyPrice), DVal(retailPrice), NotesVal(allowsNew, allowsRenewals),
_) //DateValMdy(lastUpdated))
= fields
You can see I commented out unused extractions to reduce the number of fields.
Maybe there's a better way to do this. I find this extraction technique a bit rigid, but that might be for the best.
The code is autogenerated, so you could recompile the Scala library (with settings changed) if you were only going to use the project yourself.
If you are typing out 23+ things by hand in case classes, consider grouping your values in any way that's convenient--use tuples to group things that make sense together, or use sub-case-classes to group things more tightly. It will make updating a little more awkward, but if you group things that need to be updated together it should help.
For example, try this out in Scala 2.8:
((1,2,3,4,5,6,7,8,9),(1,2,3,4,5,6),(1,2,3,4,5,6,7,8,9)).copy(_2=(4,5,6,7,8,9))
If you've already got the original in a val, it's even easier to change just one thing:
val a = (1,2,(1,2))
a.copy(_3=a._3.copy(_1=3))
See genprod.scala in the src/build directory, modify it, use it to generate the desired arity, and then recompile the library. You'll probably need to keep a modified Scala library.
Perhaps it is possible to separate those extra classes, compile them, and keep them in another jar file. I don't know, but it would be worth a try, I expect.
Or use a Map instead of a case class.
Are you writing these gargantuan case classes manually?
If you're synthesizing them programmatically, then you can always replicate what the compiler does for case classes and get essentially the same result without the Product22 limitation. Everything it does for case classes has an equivalent in Scala source for a non-case class.
精彩评论