Scala是否具有用于创建不可变数据结构的修改克隆的记录更新语法?

Ben*_*Ben 15 scala immutability

在水星我可以使用:

A = B^some_field := SomeValue
Run Code Online (Sandbox Code Playgroud)

至A与B结合的副本,除了some_fieldSomeValue不是不管它是B.我相信哈斯克尔相当于是一样的东西:

a = b { some_field = some_value }
Run Code Online (Sandbox Code Playgroud)

Scala是否有类似的东西用于"修改"不可变值.替代方案似乎是有一个构造函数直接设置实例中的每个字段,这并不总是理想的(如果构造函数应该保持不变).如果我必须明确地传递我想要修改副本的实例中的所有其他值,那么它会非常笨重而且更加脆弱.

我通过谷歌搜索,或者在语言参考手册或"Scala By Example"(我已经阅读了从头到尾,但尚未全部吸收,所以它可能好吧在那里).

我可以看到这个功能可能与Java风格的访问保护和子类有一些奇怪的交互,虽然......

Jea*_*let 26

如果将类定义为a case class,copy则会生成一个方便的方法,并调用它,您可以使用命名参数指定某些字段的新值.

scala> case class Sample(str: String, int: Int)
defined class Sample

scala> val s = Sample("text", 42)
s: Sample = Sample(text,42)

scala> val s2 = s.copy(str = "newText")
s2: Sample = Sample(newText,42)
Run Code Online (Sandbox Code Playgroud)

它甚至适用于多态案例类:

scala> case class Sample[T](t: T, int: Int)
defined class Sample

scala> val s = Sample("text", 42)
s: Sample[java.lang.String] = Sample(text,42)

scala> val s2 = s.copy(t = List(1,2,3), 42)
s2: Sample[List[Int]] = Sample(List(1, 2, 3),42)
Run Code Online (Sandbox Code Playgroud)

请注意,s2其类型不同s.


KIM*_*IMA 11

您可以为此使用案例类,但您不必这样做.案例类并不神奇 - 修饰符case只会为您节省大量的输入.通过使用命名和默认参数来实现复制方法.名称与字段相同,默认值是字段的当前值.这是一个例子:

class ClassWithCopy(val field1:String, val field2:Int) {
    def copy(field1:String = this.field1, field2:Int = this.field2) = {
        new ClassWithCopy(field1,field2);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以像使用案例类的复制方法一样使用它.命名和默认参数是一个非常有用的功能,不仅适用于复制方法.

  • 哇,我怎么想念Scala已经命名参数传递?这将非常有用.我接受了这个答案,因为它解释了案例类的复制方法是如何工作的,以及即使案例类不合适我也可以应用这些想法. (2认同)

Sea*_*ons 6

如果您计划修改的对象是 case 类,那么您可以使用自动生成的复制方法:

scala> val user = User(2, "Sen")
user: User = User(2,Sen)

scala> val corrected = user.copy(name = "Sean")
corrected: User = User(2,Sean)
Run Code Online (Sandbox Code Playgroud)