Scala 如何转换X=>;部分函数[X,R]的选项[R]

Scala 如何转换X=>;部分函数[X,R]的选项[R],scala,scala-option,partialfunction,Scala,Scala Option,Partialfunction,只要我们有一个部分函数[X,R],就很容易将其转换为返回选项[R]的函数,例如 def pfToOptf[X, R](f: PartialFunction[X,R])(x: X) = if (f.isDefinedAt(x)) Some(f(x)) else None 但是,如果任务是相反的:假设我有一个函数f获取X作为参数,并返回选项[R]。我想用它做一个部分函数[X,R]。最好的方法是什么 我想到的东西在我看来很难看: def optfToPf[X,R](f: X =>

只要我们有一个
部分函数[X,R]
,就很容易将其转换为返回
选项[R]
的函数,例如

def pfToOptf[X, R](f: PartialFunction[X,R])(x: X) =
    if (f.isDefinedAt(x)) Some(f(x))
    else None
但是,如果任务是相反的:假设我有一个函数
f
获取
X
作为参数,并返回
选项[R]
。我想用它做一个
部分函数[X,R]
。最好的方法是什么

我想到的东西在我看来很难看:

def optfToPf[X,R](f: X => Option[R]) : PartialFunction[X,R] = {
    object extractor {
        def unapply(x: X): Option[R] = f(x)
    }

    { case extractor(r) => r }
}
有没有更好的方法让我错过了呢?

这个怎么样:

Welcome to Scala version 2.8.0.r19650-b20091114020153 (Java HotSpot(TM) Client VM, Java 1.6.0_17).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def optfToPf[X,R](f: X => Option[R]): PartialFunction[X,R] = x => f(x) match {
     |     case Some(r) => r
     | }
optfToPf: [X,R](f: (X) => Option[R])PartialFunction[X,R]

scala>

我想你可以手动覆盖apply和isDefinedAt,但我会按照你觉得难看的方式来做

def optfToPf[X,R](f: X => Option[R]) = new PartialFunction[X,R] {
  def apply(x: X): R = f(x).get
  def isDefinedAt(x: X): Boolean = f(x) != None
}
测试:

scala> val map = Map(1 -> 2)
map: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)

scala> map(1)
res0: Int = 2

scala> def mapOpt(key: Int) = map.get(key)
mapOpt: (key: Int)Option[Int]

scala> mapOpt(1)
res1: Option[Int] = Some(2)

scala> mapOpt(2)
res2: Option[Int] = None

scala> val mapPf = optfToPf(mapOpt _)
mapPf: java.lang.Object with PartialFunction[Int,Int] = <function1>

scala> mapPf.isDefinedAt(2)
res3: Boolean = false

scala> mapPf.isDefinedAt(1)
res4: Boolean = true

scala> mapPf(1)
res5: Int = 2

scala> mapPf(2)
java.util.NoSuchElementException: None.get
scala>val-map=map(1->2)
map:scala.collection.immutable.map[Int,Int]=map(1->2)
scala>地图(1)
res0:Int=2
scala>defmapopt(key:Int)=map.get(key)
mapOpt:(键:Int)选项[Int]
scala>mapOpt(1)
res1:Option[Int]=Some(2)
scala>mapOpt(2)
res2:选项[Int]=无
scala>val-mapPf=optfToPf(mapOpt)
mapPf:java.lang.Object和PartialFunction[Int,Int]=
scala>mapPf.isDefinedAt(2)
res3:Boolean=false
scala>mapPf.isDefinedAt(1)
res4:Boolean=true
scala>mapPf(1)
res5:Int=2
scala>mapPf(2)
java.util.NoSuchElementException:None.get

启动
Scala 2.9
,正是这样做的:

def unlift[T, R](f: (T) => Option[R]): PartialFunction[T, R]
将函数T=>选项[R]转换为部分函数[T,R]


哦显然我需要重新调整我的大脑:)非常感谢!这应该作为
Predef
中的隐式转换提供。我想我还是更喜欢覆盖
apply
isDefinedAt
。谢谢!虽然现在我的印象是需要编写这个“转换”代码,这表明我遇到了一些问题,所以我正试图更彻底地思考。我看到的最小问题
f(x)
在任何实现中都会被调用两次(在
Some
的情况下)。是的,它会被调用两次。你可以缓存结果,但那会很尴尬,而且不是在部分函数中发生的。可能是@ToddOwen的重复我只是好奇在“这个问题以前被问过”这句话中,“before”对你意味着什么。请简单地比较两个问题的日期。关闭投票撤回。对不起,这不是“以前”的问题,而是另一个问题似乎得到了更好的答案(28票)。但现在我注意到,塞恩在这里给出了相同的答案。为了完整性,将pf
PartialFunction[X,R]
转换为
X=>Option[R]
(即
Function[X,Option[R]]]
)的标准方法是:
pf.lift
——参见: