在Scala中管理灵活的,类型化的,不可变的数据结构的正确方法是什么? [英] What is a proper way to manage flexible, typed, immutable data structures in Scala?

查看:110
本文介绍了在Scala中管理灵活的,类型化的,不可变的数据结构的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 抽象类Record {
//必填字段
val productCode:选项[字符串]
val价格:选项[双]

//可选字段
val备注:选项[字符串] =无
使用的val: Option [Boolean] = Option(false)
}

然后创建它们:

  val r =新记录{
覆盖val productCode =选项(abc)
覆盖val价格=选项(32.12)
}

有几点需要注意:


  1. 我对非可选字段使用Option,因此
    a。我不必记住哪些字段是可选的
    b。我可以在不更改界面的情况下更改哪些字段是可选的。

  2. Option选项会增加很多噪音。我非常喜欢那样的游戏,但我也不想使用空值。在使用结构时考虑所有对getOrElse的调用时尤其如此。 (我敢打赌,这种语言有一个聪明的方法来声明自动复制这些)。
  3. 这使得批量赋值(我所做的是因为我有一个字段数组)很困难一个子类将新字段混合在一起,例如:

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


    $ b

    不会编译,因为折扣没有在超类中定义,因此没有覆盖。我不确定是否有办法做到这一点。



    我的主要问题是:


    1. 是否有更好的整体方法来管理不可变数据结构?
    2. 是否有直接的方法来复制记录并只更改一个值而无需编写样板代码?
    3. li>

    例如(伪代码):

      val r2 = r.clone {覆盖val used = true} 
    解决方案

    这看起来是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中,你将不得不实现一大堆helper函数:

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

    Yuck。他们应该真的快点2.8 ...

    Right 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 things to note:

    1. I use Option for the un-optional fields so that a. I don't have to remember which fields are optional b. I can change which fields are optional without changing my interface
    2. The Option stuff adds a lot of noise. I'd love for that not to be there, but I also don't want to use nulls. This is particularly true when taking into account all the calls to getOrElse when I'm using the structure. (I bet there's a clever way for the language to declaratively autobox these.)
    3. This makes mass assignment (which I'm doing because I have an array of fields) difficult if a subclass mixes new fields in, e.g.:

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

    will not compile because discount is not defined in the superclass and therefor not an override. I'm not sure if there is a way to do this.

    My main question is:

    1. Is there a better overall way to manage immutable data structures?
    2. Is there a straightforward way to copy a record and change just one value without writing boilerplate code?

    e.g. (pseudocode}:

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

    I have heard 2.8 introduces something like this for case classes, however in a language that encourages immutable data structures, I'd be surprised to find out this is not easier before 2.8. I'm still in 2.7.

    解决方案

    This looks to be a problem very much addressed in 2.8:

    case class Employee(name: String, age: Int)
    
    val joe = Employee("Joe", 25)
    val bob = joe copy (name = "Bob")
    

    Combine this with default values, and the example you give can be easily rewritten as a case class, which I think of as the 'proper' way to implement an immutable data type. (I'm not sure if that's true for scala, but coming from ocaml/haskell, it seems right.)

    In 2.7 you're going to have to implement a whole lot of helper functions:

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

    Yuck. They should really hurry along 2.8...

    这篇关于在Scala中管理灵活的,类型化的,不可变的数据结构的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆