Immutable classes and traits?

It seems that I had a lot of problems with learning to stay with the same principles in Scala, one of which is the concept of cloning (or rather, getting) from the object in question.

One of these issues is the mixed-in-concept - an example.

trait helper //modifies some kind behavior.. assume we want to to continue down the line class A (val x:int) { def add(y:int) = new A(x + y) } Example extends App { val a =new A(5) with helper val b = a.add(10) // mixed trait disappears } 

Now this is just a very simple version of a more complex problem that I have already built today for different classes, factory methods, to hide class A, etc. If we are dealing with only one sign, I know that I can just test it and send it as necessary. But what the hell would I do if 3 or more traits existed? I would have to check out all combinations that are unrealistic.

How do you create an instance (clone) an existing object with various attributes and / or modify any aspect of it while observing the principles of functional design?

Thanks a lot, Tim

+7
source share
1 answer

The collections use implicit builders who know how to create a target type from where you start. These two types are not always the same.

There are many related posts about collector types that control what can be created, for example, http://nullary.blogspot.com/2011/10/builder-pattern-revisited-in-scala.html

Related question: if you have a collection of mixed types: Polymorphic updates in an immutable class hierarchy

On the value axis, tracking values ​​instead of coding types What is Scala equivalent to the Java builder pattern?

Updated: Something similar just appeared during the game. The use of RE in templates is described in ML and here .

 package object interpat { implicit class MySContext (val sc : StringContext) { object mys { def apply (args : Any*) : String = sc.s (args : _*) def unapplySeq (s : String) : Option[Seq[String]] = { val regexp = sc.parts.mkString ("(.+)").r regexp.unapplySeq (s) } } } implicit class SBContext (val sc : StringContext) { def sb(args: Any*): SB = new SB(sc.s (args : _*)) } implicit class toHasPattern(sb: SB) { def /(pp: String) = new SB(sb.s) with HasPattern { val p = pp } } implicit class toHasRepl(hasp: SB with HasPattern) { def /(rr: String) = new SB(hasp.s) with HasPattern with HasRepl with Updateable { val p = hasp.p val r = rr } } // disallow it implicit class noway(hasr: SB with HasPattern with HasRepl) { def /(rr: String) = ??? } implicit class noway2(hasr: SB with HasPattern with HasRepl) { def /(rr: String) = ??? } } 

Using and an alternative to managing implications with type parameters.

 package interpat { import scala.util.Try object I { def unapply(x: String): Option[Int] = Try(x.toInt).toOption } trait XX { type HasIt type Yes <: HasIt type No <: HasIt } object XX extends XX { implicit class XContext (val sc : StringContext) { def x(args: Any*) = new X[No, No] { val s = sc.s(args : _*) } } implicit class xPat(x: X[No, No]) { def /(pp: String) = new X[Yes, No] with HasPattern { val s = xs val p = pp } } implicit class xRep(x: X[Yes, No] with HasPattern) { def /(rr: String) = new X[Yes, Yes] with HasPattern with HasRepl { val s = xs val p = xp val r = rr override def toString = s replaceAll (p, r ) } } implicit class xable(xx: X[Yes, Yes]) { def x = xx.toString } } import XX._ trait X[HasP <: HasIt, HasR <: HasIt] { def s: String } trait HasPattern { def p: String } trait HasRepl { def r: String } trait Updateable { this: HasPattern with HasRepl => def update(p: String, r: String) override def toString = { update(p, r) super.toString } } class SB(val s: String) { final val sb = new StringBuilder(s) def update(p: String, r: String): Unit = sb.replace(0, sb.length, sb.toString.replaceAll(p, r)) override def toString = sb.toString } object Test extends App { val msg = "The sky is blue" match { case mys"The $thing is $colour" => mys"A $colour thing is $thing" case _ => "no match" } println (msg) val mys"The $thing is $colour" = "The sky is blue" Console println s"$thing / $colour" val mys"The ${I(number)} is blue" = "The 3 is blue" Console println s"$number" //sb"The sky is blue".update("blue","red") // no way to get a value out! sb"The sky is blue"("blue") = "red" val ugh = sb"The sky is blue" ugh("blue") = "red" Console println ugh val sx = sb"The sky is $colour" / "blue" / "red" Console println sx //sb"The sky is $colour" / "blue" / "red" / "yellow" Console println sx Console println x"The sky is $colour" / "blue" / "red" Console println (x"The sky is $colour" / "blue" / "red").x //Console println x"The sky is $colour" / "blue" / "red" / "yellow" } } 
+3
source

All Articles