在斯卡拉,“延伸(A => B)”是什么?一个案例班的意思是? [英] In Scala, what does "extends (A => B)" on a case class mean?

查看:128
本文介绍了在斯卡拉,“延伸(A => B)”是什么?一个案例班的意思是?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在研究如何在Scala中进行Memoization的研究时,我发现了一些我没有的代码。我试图看这个特别的事情,但不知道什么叫它;即所指的术语。此外,使用符号搜索并不容易,呃!



我看到以下代码在Scala中进行记忆 here

  case class Memo [A,B](f:A => B)extends(A => B){
private val cache = mutable.Map.empty [A,B]
def apply(x:A)= cache getOrElseUpdate(x,f(x))
}

这是case类的扩展,令我困惑, extends(A => B)部分。首先,发生了什么?其次,为甚么甚至需要?最后,你叫什么这样的遗产呢?即是否有一些具体的名称或术语可以用来引用它?



接下来,我看到以这种方式使用的备忘录来计算Fibanocci数字

  val fibonacci:Memo [Int,BigInt] = Memo {
case 0 => 0
case 1 => 1
case n => fibonacci(n-1)+ fibonacci(n-2)
}

这可能是我的没有看到正在应用的所有简化。但是,我无法弄清楚 val 行的结尾, = Memo {。所以,如果这更详细地输出​​了,也许我会明白备忘录正在建造的飞跃。



赞赏。谢谢。

解决方案

这个答案是由O__和Nicolas Rinaudo提供的部分答案的综合。



摘要:



有很多方便(但也是高度交织在一起)的假设由Scala编译器制作。


  1. Scala处理 extends(A => B)作为的代名词扩展Function1 [A,B] ScalaDoc for Function1 [+ T1,-R]

  2. Function1的继承抽象方法的具体实现申请(x:A):必须提供B def apply(x:A):B = cache.getOrElseUpdate(x,f(x))

  3. Scala假设隐含匹配开始于 = Memo {

  4. Scala通过内容 {} 作为Memo案例类构造函数的参数在项目3中开始

  5. Scala假定 {} 在第3项中以 PartialFunction [Int,BigInt] 开始,编译器使用match代码块作为PartialFunction方法的 apply(),然后为PartialFunction的方法 isDefinedAt()提供额外的覆盖。

详细信息:



第一个代码块定义案例类备注可以更详细地写成:

 案例类备注[A,B](f:A => B)扩展Function1 [A,B] {//替换(A => B)与Scala编译器翻译的含义
private val cache = mutable.Map.empty [A,B ]
def apply(x:A):B = cache.getOrElseUpdate(x,f(x))//在父类中定义的未实现方法的具体实现,Function1
}

定义val fibococci的第二个代码块可以更详细地写成:

  lazy val fibonacci:Memo [Int,BigInt] = {
Memo.apply(
new PartialFunction [Int,BigInt] {
override def apply(x:Int):BigInt = {
x match {
case 0 => 0
case 1 => 1
case n => fibonacci(n- 1)+ fibonacci(n-2)
}
}
覆盖def isDefinedAt(x:Int):Boolean = true
}

}
pre>

为了在第二个代码块的val中添加 lazy ,以处理自我参照问题行 case n => fibonacci(n-1)+ fibonacci(n-2)



最后,fibonacci的一个例子是:

  val x:BigInt = fibonacci(20)//返回6765(几乎立即)
pre>

In researching how to do Memoization in Scala, I've found some code I didn't grok. I've tried to look this particular "thing" up, but don't know by what to call it; i.e. the term by which to refer to it. Additionally, it's not easy searching using a symbol, ugh!

I saw the following code to do memoization in Scala here:

case class Memo[A,B](f: A => B) extends (A => B) {
  private val cache = mutable.Map.empty[A, B]
  def apply(x: A) = cache getOrElseUpdate (x, f(x))
}

And it's what the case class is extending that is confusing me, the extends (A => B) part. First, what is happening? Secondly, why is it even needed? And finally, what do you call this kind of inheritance; i.e. is there some specific name or term I can use to refer to it?

Next, I am seeing Memo used in this way to calculate a Fibanocci number here:

  val fibonacci: Memo[Int, BigInt] = Memo {
    case 0 => 0
    case 1 => 1
    case n => fibonacci(n-1) + fibonacci(n-2)
  }

It's probably my not seeing all of the "simplifications" that are being applied. But, I am not able to figure out the end of the val line, = Memo {. So, if this was typed out more verbosely, perhaps I would understand the "leap" being made as to how the Memo is being constructed.

Any assistance on this is greatly appreciated. Thank you.

解决方案

This answer is a synthesis of the partial answers provided by both 0__ and Nicolas Rinaudo.

Summary:

There are many convenient (but also highly intertwined) assumptions being made by the Scala compiler.

  1. Scala treats extends (A => B) as synonymous with extends Function1[A, B] (ScalaDoc for Function1[+T1, -R])
  2. A concrete implementation of Function1's inherited abstract method apply(x: A): B must be provided; def apply(x: A): B = cache.getOrElseUpdate(x, f(x))
  3. Scala assumes an implied match for the code block starting with = Memo {
  4. Scala passes the content between {} started in item 3 as a parameter to the Memo case class constructor
  5. Scala assumes an implied type between {} started in item 3 as PartialFunction[Int, BigInt] and the compiler uses the "match" code block as the override for the PartialFunction method's apply() and then provides an additional override for the PartialFunction's method isDefinedAt().

Details:

The first code block defining the case class Memo can be written more verbosely as such:

case class Memo[A,B](f: A => B) extends Function1[A, B] {    //replaced (A => B) with what it's translated to mean by the Scala compiler
  private val cache = mutable.Map.empty[A, B]
  def apply(x: A): B = cache.getOrElseUpdate(x, f(x))  //concrete implementation of unimplemented method defined in parent class, Function1
}

The second code block defining the val fibanocci can be written more verbosely as such:

lazy val fibonacci: Memo[Int, BigInt] = {
  Memo.apply(
    new PartialFunction[Int, BigInt] {
      override def apply(x: Int): BigInt = {
        x match {
          case 0 => 0
          case 1 => 1
          case n => fibonacci(n-1) + fibonacci(n-2)
        }
      }
      override def isDefinedAt(x: Int): Boolean = true
    }
  )
}

Had to add lazy to the second code block's val in order to deal with a self-referential problem in the line case n => fibonacci(n-1) + fibonacci(n-2).

And finally, an example usage of fibonacci is:

val x:BigInt = fibonacci(20) //returns 6765 (almost instantly)

这篇关于在斯卡拉,“延伸(A => B)”是什么?一个案例班的意思是?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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