How can I manage flexible, typed, immutable data structures in Scala?

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 notes:

  • I use Option for optional fields to a. I do not need to remember which fields are optional b. I can change which fields are optional without changing the interface.
  • The Option property adds a lot of noise. I would like this not to be, but I also do not want to use zeros. This is especially true considering all the calls to getOrElse when I use the structure. (I am sure there is a smart way for a language to declaratively do this automatically.)
  • This makes bulk assignment (which I do because I have an array of fields) difficult if the subclass mixes the new fields, for example:

    override val List(productCode, price, discount) = fields // fields is a List

, discount . , .

:

  • ?
  • ?

. (}:

val r2 = r.clone { override val used = true }

, 2.8 - case, , , , , 2.8. 2.7.

+3
5

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 :

def asUsed(r: Record): Record = {
  Record(r.productCode, r.price, r.nodes, Some(true))
}

. 2.8...

+2

. FWIW, , , . , List : hd tl. .

, . .

. , , .

Scala, Option. , .

+2

Option , , : ?

0

Well, as already mentioned, there is no direct way in the current (2.7) Scala to do this, but from my point of view it can be done quite easily with the builder pattern. Code for demo:

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)
}
class RecordBuilder{
  private var _productCode:Option[String] = null
  private var _price:Option[Double] = null

  // Optional fields
  private var _notes:Option[String] = None
  private var _used:Option[Boolean] = Option(false)

  def productCode(in:Option[String]) : RecordBuilder = {
    _productCode = in
    this
  }
  def price(in : Option[Double]) : RecordBuilder = {
    _price = in
    this
  }
  def notes(in:Option[String]) : RecordBuilder = {
    _notes = in
    this
  }
  def used (in : Option[Boolean]) : RecordBuilder = {
    _used = in
    this
  }

  def create() : Record  =  {
   val r =  new Record = {
      override productCode = _productCode
      override price = _price
      override notes = _notes
      override used  = _used

    }
  r
}
}
object Record{
  def from(in:Record) : RecordBuilder = {
    val r = new RecordBuilder
    r.productCode(in.productCode).price(in.price).notes(in.notes)
    .used(in.used)
  }
}
object Test {
  def main(args:Array[String]) = {
    val r = new Record {
    override val productCode = Option("abc")
    override val price = Option(32.12)}
  }
  val r1 = Record.from(r).used(true).create
}
0
source

Lenses are a great tool for working with immutable data structures. See this question .

0
source

Source: https://habr.com/ru/post/1722495/


All Articles