Scala部分函数与具体部分函数

Scala部分函数与具体部分函数,scala,partialfunction,Scala,Partialfunction,有没有什么快速的方法可以作为一个具体的函数(例如,(a)=>B)作为部分函数[a,B]?我所知道的最简洁的语法是: (a: A) => a match { case obj => func(obj) } 是否在任何地方都存在隐式转换,例如: implicit def funcAsPartial[A, B](func: A => B) = new PartialFunction[A, B] { def isDefinedAt(a: A) = true def appl

有没有什么快速的方法可以作为一个具体的函数(例如,
(a)=>B
)作为
部分函数[a,B]
?我所知道的最简洁的语法是:

(a: A) => a match { case obj => func(obj) }
是否在任何地方都存在隐式转换,例如:

implicit def funcAsPartial[A, B](func: A => B) = new PartialFunction[A, B] {

  def isDefinedAt(a: A) = true
  def apply(a: A) = func(a)

}

我想我只是写了我想要的东西,但是Scala库中已经有了吗?

没有,几个月前我试着找到了一个,结果我自己写了一个,基本上和你的一样。

用隐式转换做这件事是危险的,原因与
(a)相同=>B
不应从
部分函数[A,B]
继承。也就是说,PartialFunction的契约保证您可以在
isDefinedAt
返回
true
的任何位置安全地*调用
apply
。职能1的合同未提供此类担保

如果将隐式转换应用于未在任何地方定义的函数,则会导致PartialFunction违反其约定。相反,使用皮条客明确转换:

implicit def funcAsPartial[A, B](f: A => B) = new {
   /** only use if `f` is defined everywhere */
   def asPartial(): PartialFunction[A, B] = {
      case a => f(a)
   }

   def asPartial(isDefinedAt: A => Boolean): PartialFunction[A, B] = {
      case a if isDefinedAt(a) => f(a)
   }
}

// now you can write
val f = (i: Int) => i * i

val p = f.asPartial // defined on all integers
val p2 = f.asPartial(_ > 0) // defined only on positive integers

*正如评论中所讨论的,这里“安全”的含义可能并不完全清楚。我的想法是,PartialFunction明确声明其域的精确含义如下:如果
isDefinedAt
为值
x
返回true,那么
apply(x)
可以按照函数作者的意图进行计算。这并不意味着
apply(x)
不会抛出异常,而仅仅是异常是函数设计的一部分(应该记录在案)。

在我看来
(A)=>B
应该继承自
部分函数[A,B]
,而不是相反。我同意这一点,因为A(total)函数是一个局部函数,碰巧在任何地方都定义了(isDefinedAt(x)=true)但是,Martin Odersky说,函数不能保证是一个完整的函数,只是它的域没有文档记录。所以PartialFunction是一个记录其域的函数。谢谢;我有一个错误的想法,即Function1意味着在整个域上定义。@AaronNovstrup:您对PartialFunction契约的解释是唯一有意义的,但ScalaDocs(至少在2.9.1之前)没有反映出来。
PartialFunction
的ScalaDocs声称:“类型为
PartialFunction[A,B]
的部分函数是一元函数,其中域不一定包含类型为
A
的所有值。”此外,他们从不声称在定义的任何地方调用f都是安全的(在什么意义上),这很容易违反,就像
PartialFunction
literal
{case 0=>1/0}
。你是从哪里得到这些信息的?是否需要提交错误报告?@Blaisorblade我相信我在学习Scala时(已经有一段时间了)在邮件列表上读到了这个解释,我在写这个答案时没有看任何文档。是的,违反这个合同很容易,甚至有些常见(例如,在catch块中包装/重新显示异常)。真正的问题是,partialfunction定义了它们的域,而普通函数则没有定义它们的域(这实际上意味着什么)@Blaisorblade文档可能应该按照我刚才添加到答案中的更改进行修订。在搜索现有的错误报告时,我从Odersky找到了以下解释-与您阅读的内容相符:。我为文档创建了一个错误报告,如前所述,链接回此处并引用您的姓名和建议: