2

I am new to Scala but an experienced programmer trying to shed old habits and get on board with functional style. A simple program I'm designing involves questions / answer objects and retains some basic facts about success. This alone would be easy enough using immutable objects - but part of my objective is to link associated facts, so the program might ask them once in awhile next to each other. (Example: "The Knight Rider Car was?" , "What TV show features an Impala? )

In Java I might have just linked associated objects like I've written below, but immutable laws prevent this (I can't link A-> B and instantiate B -> A unless I do it in one shot?)

And I must admit, this is probably a good thing - maybe functional style is designed to prevent this kind of circular referencing. But I'm at a loss how to correct the problem. My design would fail once a question is asked - for this returns a copy object with new values of "right , asked" so object linking seems like a pitfall again. My best guess is to build relation sets in a helper object, based on Q/A data only, but I'd like to avoid juggling a separate data pattern object.

Thank you all - Tim in Columbus Ohio

case class FactItem (

    q:String, a:String,
    right: Double = 0.0,
    asked: Double = 0.0,
    linked: List[FactItem] = List[FactItem]()

    ) { 

  def rP = right / asked //right per

  def subLink( l:List[FactItem] ) : FactItem =  {
    this.copy( linked = l-this)

  } 
Alex Lockwood
  • 81,274
  • 37
  • 197
  • 245
LaloInDublin
  • 5,167
  • 4
  • 19
  • 23
  • Hey I'm from Dublin too! But seriously, I don't think putting that information in your username is a particularly good idea. – Hassan Jun 05 '12 at 23:04
  • You can (and should... if you want people to answer your questions) use **code blocks** by placing 4 spaces before each line of code :). – Alex Lockwood Jun 05 '12 at 23:25
  • It can be done, and in the FP world this is known as "tying the knot". However, I'm not sure how to do this in Scala, so I re-asked a simplified version of your question: http://stackoverflow.com/questions/10906797/letrec-in-scala – Dan Burton Jun 06 '12 at 00:38

2 Answers2

2

See this question for how to do this immutably: scala: how to model a basic parent-child relation

Tip: don't do this in a case class unless you override toString to not include the list of items (you'll overflow the stack if there are circular references, since the toString of this item includes the toString of all the others in the List).

You may save yourself a lot of headaches by making the List a private var and updating all your instances from your factory method in the companion object that creates all the items, once you have references to the list items. With no public setters it's still effectively immutable.

A similar and perhaps theoretically more sound approach would be to make the list a Stream that gets its values from a map in the companion object. The map has to be mutable while the items are being created, but at least the items are now fully immutable.

Community
  • 1
  • 1
Luigi Plinge
  • 48,746
  • 19
  • 105
  • 173
  • Thank you Luigi that helps a lot, and also answers a fear I had when I noticed Scala recursively executes "ToString" on a case class! – LaloInDublin Jun 06 '12 at 00:22
2

The real answer is don't do that. Create a "Relation" object that points to both.

Now you'll probably wonder how do you go from an object pointed to "Relation" to "Relation" itself and then the other object, and you do that by using zippers. Instead of going directly to object "a", you get the tree/graph, and move a zipper to "a". From there, you can go back to "Relation" and forward to "b", or directly from "a" to "b" if the zipper knows lateral movement.

Unfortunately, Scala is way behind Haskell when it comes to useful zippers. But you can always create one for your data structure if you understand the concept (which I'll leave you to research about).

There's still another answer which may apply. You may have a "Lens" which is an object who knows how to pick apart and put together (with modification) some other object. The basic design of the class will have to allow for it (with mutability or laziness tricks), but the lens hides the ugliness of the operation itself (beyond providing a number of other nifty features).

Finally, I want to emphasize that Scala is not purely functional for good reason: Odersky thinks there's value outside pure functional languages, and wants you to have that power available.

Daniel C. Sobral
  • 284,820
  • 82
  • 479
  • 670