Scala的“案例类”中的“案例”一词是什么意思?

时间:2019-08-21 14:31:25

标签: scala terminology case-class

我知道case class会导致编译器使用样板扩展class来实现某种有用的模式(“ plain and immutable data-holding objects that should exclusively depend on their constructor arguments”)。

但是在这种情况下,“案例”一词本身对我没有任何意义。我习惯将它用作C#中switch语句的一部分,但这似乎与Scala使用该词无关。

当我可以将单词附加到特定含义时,我发现更容易编程。现在,我的心理模型是case => boilerplate,就像它可能是blurg => boilerplate一样。这是一种有效的思维模式,但是模棱两可使人们容易误解或完全忘记。

那么case一词与编译器的实际作用有什么关系?

我不是在寻找“设计师的想法”,而是“在给定语言设计常识的情况下,将这个术语与其含义联系起来的一种合理方法”。

2 个答案:

答案 0 :(得分:3)

我认为,术语case来自case analysis,这是一种通过称为algebraic data types的特殊结构实现的推理技术。 case中的case class本身可能没有多大意义,但是当它构成sealed结构的一部分时,例如Scala定义ADT的方式

sealed trait Number
case object Zero extends Number
case class Succ(v: Number) extends Number

然后我们看到构造Number的两种形式,即使用ZeroSucc 构造函数。因此,每当我们不得不考虑Number时,我们至少知道要考虑两个不同的case。例如,假设我们要在Number上定义加法,那么它的定义将不得不处理两种情况,也许像这样

def sum(a: Number, b: Number): Number =
  a match {
    case Zero => b
    case Succ(v) => Succ(sum(v, b))
  }

其中

sum(Succ(Zero), Succ(Zero)) == Succ(Succ(Zero)) // 1 + 1 = 2
sum(Succ(Succ(Zero)), Succ(Zero)) == Succ(Succ(Succ(Zero))) // 2 + 1 = 3
sum(Succ(Zero), Succ(Succ(Zero))) == Succ(Succ(Succ(Zero))) // 1 + 2 = 3
sum(Zero, Succ(Succ(Zero))) == Succ(Succ(Zero)) // 0 + 2 = 2
sum(Succ(Succ(Zero)), Zero) == Succ(Succ(Zero)) // 2 + 0 = 2

请注意,为了定义ADT,Scala如何使用classobjecttrait等术语,这些术语似乎来自于面向对象的范例,但是从概念上讲,ADT几乎没有与OO中的类层次结构相同。我个人觉得这很令人困惑,但是我们必须记住Scala既是功能语言又是OO语言,这可能是造成此类术语溢出的原因。在其他一些更“纯”的语言中,ADT的case class仅用竖线|表示,就像这样

Inductive nat : Type :=
   | O : nat
   | S : nat -> nat.

我的建议是尽量不要成为“言语的奴隶”,而应该为你服务。重要的是单词或术语后面的含义,而不是单词本身。不要围绕术语构建思维模型,而应围绕它们为穿越沟通薄弱而努力奋斗的沉重概念构建思维模型。我认为case正在尝试传达的概念是ADT。

答案 1 :(得分:-1)

C#具有android:launchMode="singleInstance" / switch语言功能,该功能允许通过将输入与一组可能的值进行匹配来控制程序流。

case

在这里,public static GetEmail(string name) { switch (name) { case "bill": return "bill@example.com"; case "jane": return "jane@example.com"; default: return null; } } 大致意味着“在给定值等于该值的情况下,执行X。”

Scala的case / match功能类似于C#的功能。

case

但是它功能更强大。它旨在针对比字符串更复杂的事物评估“匹配”。要利用这一强大的匹配功能,您可以使用def getEmail(name: String): Option[String] = { name match { case "bill" => Option("bill@example.com") case "jane" => Option("jane@example.com") case _ => None } } 定义不可变的数据保存类。

这是一个简单但希望有帮助的案例类示例,它与case class / match一起使用:

case

简而言之,case class Person(name: String, hasEmail: Boolean) object EmailHelper { def getEmail(person: Person): Option[String] = { person match { case Person(_, false) => None case Person("bill", true) => Option("bill@example.com") case Person("jane", true) => Option("jane@example.com") case _ => None } } } 强制执行一组约束,这些约束使一个类可用于case class / match