在斯卡拉,“延伸(A => B)”是什么?一个案例班的意思是? [英] In Scala, what does "extends (A => B)" on a case class mean?
问题描述
我看到以下代码在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编译器制作。
- Scala处理
extends(A => B)
作为的代名词扩展Function1 [A,B]
( ScalaDoc for Function1 [+ T1,-R] ) - Function1的继承抽象方法的具体实现
申请(x:A):必须提供B
def apply(x:A):B = cache.getOrElseUpdate(x,f(x))
- Scala假设隐含
匹配
开始于= Memo {
- Scala通过内容
{}
作为Memo案例类构造函数的参数在项目3中开始 - 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] = {
pre>
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
}
)
}
为了在第二个代码块的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.
- Scala treats
extends (A => B)
as synonymous withextends Function1[A, B]
(ScalaDoc for Function1[+T1, -R])- 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))
- Scala assumes an implied
match
for the code block starting with= Memo {
- Scala passes the content between
{}
started in item 3 as a parameter to the Memo case class constructor- Scala assumes an implied type between
{}
started in item 3 asPartialFunction[Int, BigInt]
and the compiler uses the "match" code block as the override for the PartialFunction method'sapply()
and then provides an additional override for the PartialFunction's methodisDefinedAt()
.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 linecase 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屋!