Scala 如何在模式匹配保护中避免显式.isDefinedAt()调用

Scala 如何在模式匹配保护中避免显式.isDefinedAt()调用,scala,pattern-matching,partialfunction,Scala,Pattern Matching,Partialfunction,我有一些基于Akka的参与者系统,其中多种参与者基于相同的模板,因为这些参与者只因响应值的类型不同。例如: 最终案例类请求(数据:任何) 最终案例类响应(数据:任何) 抽象类ActorTemplate[T]扩展了Actor{ def dataFunction:PartialFunction[Any,T] def响应(数据:T):响应 def接收:接收={ 如果dataFunction.isDefinedAt(数据)=> 发送者!响应(数据函数(数据)) } } 部分函数有一种避免类

我有一些基于Akka的参与者系统,其中多种参与者基于相同的模板,因为这些参与者只因响应值的类型不同。例如:

最终案例类请求(数据:任何)
最终案例类响应(数据:任何)
抽象类ActorTemplate[T]扩展了Actor{
def dataFunction:PartialFunction[Any,T]
def响应(数据:T):响应
def接收:接收={
如果dataFunction.isDefinedAt(数据)=>
发送者!响应(数据函数(数据))
}      
}
部分函数有一种避免类型擦除的方法,它使我无法简单

def接收:接收={
案例请求(数据:T)=>
发送者!响应(数据)
同时强迫我生成
if-dataFunction.isDefinedAt(data)
guard-on模式,我只是不太喜欢它

是否有任何方法避免明确的防护

目前我唯一能找到的方法就是引入一些愚蠢的提取器:

对象数据提取器{
未应用def(数据:任意):选项[T]=
if(dataFunction.isDefinedAt(data))Some(dataFunction(data))else None
}
def接收:接收={
案例请求(数据提取器(数据)=>
发送者!响应(数据)
但可能它已经在标准库中的某个地方完成了?或者可能有其他类似于collections
collect
方法的方法,但用于匹配

结论 经过一些思考,我回到了提取器对象,并借助@pagoda_5b建议将其转化为特征:

trait PFExtract[T] {
 object PF {
   def unapply(any: Any)(implicit pf: PartialFunction[Any, T]): Option[T] =
     pf.lift(any)
 }
}

我实际要做的是在
dataFunction
上使用
applyOrElse
方法,在未为给定输入定义部分函数时定义默认响应

def defaultAnswer: T

def receive: Receive = {
  case Request(data) =>
    sender ! respond(dataFunction.applyOrElse(data, defaultAnswer))
}
如果您喜欢将答案包装在
选项中
,那么已经有一个名为
lift
的方法可以为您完成这一任务,正如您正确猜测的那样

def receive: Receive = {
  case Request(data) =>
    sender ! respond(dataFunction.lift(data))
}
如果没有为数据定义函数,您甚至可以决定不回答

def receive: Receive = {
  case Request(data) =>
    dataFunction.lift(data).foreach {
      sender ! respond(_)
    }
}

foreach
选项上定义的
类型仅当有一些内容可用时(即,如果您有
some(…)

dataFunction
的类型签名似乎拼写错误。它应该是
PartialFunction[Any,T]
pagoda_5b有很好的建议,但是你的提取器也很不错。@sourcedelica已经用@pagoda 5b“拉”了它。提升(…)建议:
def unapply(key:Any):Option[K]=keytranformer.lift(key)
好吧,这是可能的解决方案,谢谢!但是:1.如果我们不想调用
响应
而使用
默认值
的话,只有第三种解决方案有效;2.虽然前两种解决方案提供了一些方法,可以向
发送方
提供一些关于不适用数据的反馈,但第三种解决方案会悄悄地将其抛出。再次感谢,这些都是值得思考的。@Seigert我提出了三种解决方案,因为从你的帖子中,我不确定你更喜欢用什么方式来处理“意外数据”。