我读到了scala匿名函数这里,并看到它们可以采用这种格式:
{ case p1 => b1 … case pn => bn }然而,我认为这就是部分函数的编写方式。实际上,在这篇博客文章中,作者将部分函数称为匿名函数。起初,他说collect接受一个部分函数,但后来似乎称它为匿名函数("collect可以处理匿名函数.“)。
只是某些匿名函数是部分函数吗?如果是的话,部分函数都是匿名的吗?或者只有在像阿尔文·亚历山大( Alvin Alexander)的例子这样的格式下,它们才是匿名的:
val divide2: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 42 / d
}发布于 2020-08-23 00:06:37
从您链接的模式匹配匿名函数的文档中:
如果期望的类型是SAM-可转换为
scala.Functionk[S1,…,Sk, R],则表达式将被视为等效于匿名函数: (x1:S1,…,xk:Sk) => (x1,…),xk)匹配{ case p1 => b1…案例pn => bn } 在这里,每一个习都是一个新的名字。如这里所示,这个匿名函数依次等价于下面的实例创建表达式,其中T是所有bi类型的弱最小上限。 新scala.FunctionkS1,…,Sk,T{应用(x1:s1,…),xk:Sk):t= (x1,…),xk)匹配{ case p1 => b1…案例pn => bn } 如果期望的类型是scala.PartialFunction[S, R],则将该表达式视为等效于以下实例创建表达式: 新scala.PartialFunctionS,T{ def应用(x: S):t=x match { case p1 => b1…情况pn => bn } def isDefinedAt(x: S):Boolean ={ case p1 => =>…情况pn => true case _ => false }
第一个代码片段是一个模式匹配的匿名函数,但不一定是一个部分函数。只有当它被赋予具有PartialFunction参数的方法或分配给类型为PartialFunction的变量时,它才会被转换为PartialFunction。
因此,您是正确的,只有一些(模式匹配)匿名函数是部分函数(AFAIK,使用fat箭头(如x => x )定义的函数文本只能用于创建FunctionN实例,而不能用于创建PartialFunction实例)。
然而,并不是所有的部分函数都是匿名函数。定义PartialFunctions的一种无糖方法是扩展PartialFunction特性(扩展Function1)并手动重写isDefinedAt和apply方法。例如,也可以使用匿名类定义divide2:
val divide2 = new PartialFunction[Int, Int] {
override def isDefinedAt(x: Int) = x != 0
override def apply(x: Int) = 42 / x
}但是,您可能不会经常看到这种情况,因为只使用模式匹配来定义PartialFunction要容易得多。
在Alexander链接的博客文章中,作者提到了将匿名部分函数文字匹配为匿名函数的模式,这仅仅是因为它既是一个部分函数,也是一个匿名函数。您还可以像这样定义函数:
List(42, "cat").collect(new PartialFunction[Any, Int] {
def isDefinedAt(x: Any) = x.isInstanceOf[Int]
def apply(x: Any) = x match {
case i: Int => i + 1
}
})它不再是一个匿名函数,尽管它仍然是一个匿名对象--匿名类的实例。或者您可以预先定义一个单例对象,然后使用它。
object Foo extends PartialFunction[Any, Int] {
def isDefinedAt(x: Any) = x.isInstanceOf[Int]
def apply(x: Any) = x match {
case i: Int => i + 1
}
}
List(42, "cat").collect(Foo)不管你怎么定义它,它都是一个部分函数。
发布于 2020-08-22 19:45:05
匿名和局部是不同的概念。我们不会说下面的函数是匿名的
val divide2: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 42 / d
}因为它绑定到名称divide2,所以我们可以说divide2是用匿名(函数)值定义的。
{ case d: Int if d != 0 => 42 / d }在同样的意义上,x定义为以下定义中的匿名值42
val x: Int = 42部分的正交概念是指函数的特殊子类型,而不是特定类型的值是否绑定到名称。
发布于 2020-08-22 19:27:10
下面是另一种编写模式匹配部分函数的方法。
val divide = new PartialFunction[Int, Int] {
def apply(x: Int) = 42 / x
def isDefinedAt(x: Int) = x != 0
}本质上,部分函数是没有为一组输入定义的函数。就像在这个例子中,用0除以0是没有意义的,或者您可以限制一些特定的值。
部分功能的巧妙之处在于它与orElse、andThen和collect具有协同作用。取决于您是否要在除法函数中输入0,如果变量不是0,则可以传递给andThen,如果是0,则可以通过orElse传递。最后,只有在对输入定义了部分函数时,collect才会应用它。
创建部分函数的方法通常是通过模式匹配和大小写进行匹配,如示例所示。
最后一点,Scala中的匿名函数就像Python中的lambda。这只是一种不用“命名”就可以创建函数的方法。
例如
val f: Int => Int = (x: Int) => x * x
collect {
case a: Int => 1-a
}https://stackoverflow.com/questions/63540024
复制相似问题