【问题标题】:Difference between instantiating something from the class and from the companion object从类实例化某些东西和从伴随对象实例化的区别
【发布时间】:2019-05-20 23:10:29
【问题描述】:

我正在阅读和练习 Scala 中的函数式编程一书。在关于属性测试的章节中,一个练习要求实现def listOf[A](g: Gen[A]): SGen[List[A]],下面是相关代码:

case class Gen[+A](sample: State[RNG, A]) {

  def flatMap[B](f: A ⇒ Gen[B]): Gen[B] =
    Gen(sample.flatMap(f(_) sample))

  /* A method alias for the function we wrote earlier. */
  def listOfN(size: Int): Gen[List[A]] =
    Gen.listOfN(size, this)

  def listOfN(size: Gen[Int]): Gen[List[A]] =
    size flatMap (Gen listOfN (_, this))
}

object Gen {
  def listOfN[A](n: Int, g: Gen[A]): Gen[List[A]] =
    Gen(State.sequence(List.fill(n)(g.sample)))

  def listOf[A](g: Gen[A]): SGen[List[A]] =
  //  SGen { n ⇒ g.listOfN(n) }
  //  SGen{listOfN(_, g)}
}

case class SGen[+A](forSize: Int ⇒ Gen[A])

如你所见,listOf[A](g: Gen[A]): SGen[List[A]]有两种实现方式,第二种是我想到的,第一种是书上提供的解决方案。

我的问题是,通过伴随对象创建 SGen 和使用生成器 g 上的 listOfN 方法创建它之间有什么区别吗?我想只要两种实现最终都使用g 来生成值,差别不大。

【问题讨论】:

    标签: scala scalacheck property-based-testing


    【解决方案1】:

    在这个例子中确实没有实际的区别。从实现中可以看出Gen.listOfN(size: Int) 只是在调用伴生对象实现。方法别名的优点之一是您可以在伴随对象中使用更简单的语法,如下所示:

    object Gen {
        ...
        def listOf[A](g: Gen[A]): SGen[List[A]] =
            SGen(g.listOfN)
    }
    

    当用户创作更大的作品时,拥有这些不同的语法选项可以对清晰度产生更大的影响。

    【讨论】:

    • 谢谢,有没有什么显着不同的例子?
    猜你喜欢
    • 1970-01-01
    • 2016-10-04
    • 2013-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多