2

This is a follow-up now that Scala 2.8.0 beta 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.

Community
  • 1
  • 1
Alex Neth
  • 3,326
  • 2
  • 26
  • 36
  • I am not synthesizing programmatically. This is an internal reflection of a record I'm importing that has many fields. Grouping related fields would be make my extraction code pretty ugly. @Rex no offense, but that example ain't pretty. I knocked down the number of fields for now, but this seems like a rather silly limitation for a language to have.... I'm desperately trying to avoid generic hashtables and have for now.... Added import code example above. – Alex Neth Feb 09 '10 at 07:16
  • What @Rex meant to say is that the code that generates the Product classes -- the reason for your current predictment -- is auto-generated. He is suggesting that you generate a new library with a different setting, which, by the way, is really the only alternative if you intend to use case classes. – Daniel C. Sobral Feb 09 '10 at 10:58

3 Answers3

4

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))
Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • I don't know about tuples - a.copy(_3=a._3.copy(_1=3)) would send a lot of people running, but perhaps sub-case-classes is a good solution. – Alex Neth Feb 09 '10 at 07:22
  • Tuples are just pre-defined case classes. It's a lot clearer with your own code--it'd look more like `record.copy(customer=record.customer(lastname="Smith"))`. – Rex Kerr Feb 09 '10 at 16:11
2

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.

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • Thanks for the suggestion. I don't want to use a map (lose type-safety which is half the point of Scala). I also don't want to keep my own core scala library. As it stands, I just reduced the number of fields. It's a strange limitation in the language... Overall, though, Scala 2.8 is a massive improvement in usability with default and named parameters. – Alex Neth Feb 09 '10 at 23:45
1

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.

Randall Schulz
  • 26,420
  • 4
  • 61
  • 81
  • I wouldn't say they are gargantuan... and it's just one class. But I don't like the idea of writing a constructor and copy method to keep in sync. – Alex Neth Feb 09 '10 at 07:20