Scala 如何在模式匹配保护中避免显式.isDefinedAt()调用
我有一些基于Akka的参与者系统,其中多种参与者基于相同的模板,因为这些参与者只因响应值的类型不同。例如:Scala 如何在模式匹配保护中避免显式.isDefinedAt()调用,scala,pattern-matching,partialfunction,Scala,Pattern Matching,Partialfunction,我有一些基于Akka的参与者系统,其中多种参与者基于相同的模板,因为这些参与者只因响应值的类型不同。例如: 最终案例类请求(数据:任何) 最终案例类响应(数据:任何) 抽象类ActorTemplate[T]扩展了Actor{ def dataFunction:PartialFunction[Any,T] def响应(数据:T):响应 def接收:接收={ 如果dataFunction.isDefinedAt(数据)=> 发送者!响应(数据函数(数据)) } } 部分函数有一种避免类
最终案例类请求(数据:任何)
最终案例类响应(数据:任何)
抽象类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接收:接收={
案例请求(数据提取器(数据)=>
发送者!响应(数据)
但可能它已经在标准库中的某个地方完成了?或者可能有其他类似于collectionscollect
方法的方法,但用于匹配
结论
经过一些思考,我回到了提取器对象,并借助@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我提出了三种解决方案,因为从你的帖子中,我不确定你更喜欢用什么方式来处理“意外数据”。