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

发布于 2024-11-19 14:50:46 字数 540 浏览 0 评论 0原文

在 Mercury 中,我可以使用:

A = B^some_field := SomeValue

将 A 绑定到 B 的副本,但 some_fieldSomeValue 而不是 B 中的任何值。我相信 Haskell 的等价物是这样的:

a = b { some_field = some_value }

Scala 是否有类似的东西来“修改”不可变值。另一种选择似乎是有一个构造函数直接设置实例中的每个字段,但这并不总是理想的(如果构造函数应该维护不变量)。另外,如果我必须显式传递我想要修改副本的实例中的所有其他值,那么它会非常笨重且更加脆弱。

我无法通过谷歌搜索找到任何关于此的信息,或者在语言参考手册或“Scala By Example”的简短调查中找不到任何关于此的信息(我已经从头到尾阅读过,但还没有吸收全部内容,所以它可能我们就在那里)。

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

In Mercury I can use:

A = B^some_field := SomeValue

to bind A to a copy of B, except that some_field is SomeValue instead of whatever it was in B. I believe the Haskell equivalent is something like:

a = b { some_field = some_value }

Does Scala have something like this for "modifying" immutable values. The alternative seems to be to have a constructor that directly sets every field in the instance, which isn't always ideal (if there are invarients the constructor should be maintaining). Plus it would be really clunky and much more fragile if I had to explicitly pass every other value in the instance I want to have a modified copy of.

I couldn't find anything about this by googling, or in a brief survey of the language reference manual or "Scala By Example" (which I have read start-to-finish, but haven't absorbed all of yet, so it may well be in there).

I can see that this feature could have some weird interactions with Java-style access protection and subclasses though...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瞎闹 2024-11-26 14:50:46

如果将类定义为 case 类,则会生成一个方便的 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)

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

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)

请注意,s2 的类型与 s 不同。

If you define your class as a case class, a convenient copy method is generated, and calling it you can specify with named parameters new values for certain fields.

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)

It even works with polymorphic case classes:

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)

Note that s2 has a different type than s.

尹雨沫 2024-11-26 14:50:46

您可以为此使用案例类,但不是必须这样做。案例类并没有什么神奇之处 - 修饰符 case 只是为您节省了大量的打字时间。
复制方法是通过使用命名参数和默认参数来实现的。名称与字段相同,默认值是字段的当前值。这是一个示例:

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

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

You can use case classes for this, but you don't have to. Case classes are nothing magical - the modifier case just saves you a lot of typing.
The copy method is realized by the use of named and default parameters. The names are the same as the fields and the defaults are the current values of the fields. Here's an example:

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

You can use this just like the copy method on case classes. Named and default parameters are a very useful feature, and not only for copy methods.

久隐师 2024-11-26 14:50:46

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

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

scala> val corrected = user.copy(name = "Sean")
corrected: User = User(2,Sean)

If the object you're planning on modifying is a case class then you can use the autogenerated copy method:

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

scala> val corrected = user.copy(name = "Sean")
corrected: User = User(2,Sean)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文