2014-01-29 49 views
1

我有一个昂贵的case语句,它需要命中数据库以确定一个完整匹配。如果有匹配,从上述调用的结果必须被用来进行进一步的操作:从Scala模式匹配中的昂贵语句别名对象

def intent = { 
    case request @ GET(Path(Seg(database :: Nil))) if recordsFrom(database) != Nil => 
     renderOutput(recordsFrom(database)) 
    case ... 
} 

我想打电话给recordsFrom(database)只有一次。在上面的例子中,它被调用两次。似乎我应该可以在陈述中应用一些别名?

回答

2

出了什么问题:

def intent = { 
    case request @ GET(Path(Seg(database :: Nil))) => 
    val records = recordsFrom(database) 
    if(!records.isEmpty){ 
     renderOutput(records) 
    } else { 
     ... 
    } 
    case ... 

你可以,如果你想避免过多的嵌套块第一种情况下的身体移动到不同的功能。

+0

当数据库不包含记录时,这将导致匹配。对于这个人为的例子来说也许很好,但是对于产生的部分函数会产生非常不同的行为。 –

+0

那又如何?您可以根据您的请求进行匹配,使用数据库检索记录列表,然后测试以查看列表是否为空,您可以在if语句中处理这两种情况。模式匹配很酷,但它不是每个问题的答案。 – vptheron

3

Lawrence,从我看到你正在使用Unfiltered来处理RESTful请求,但是你还将数据库查找与该响应筛选结合起来。我会建议你不要这样做。相反,我会安排你的事情如下:

val dbReqCommand = new DBRequestCommand(myDbConPool) 

def intent ={ 
    case req @ GET(Path(Seq(database :: Nil))) => dbReqCommand(req, database) 
} 

其中你封装在一个对象数据库的请求,你可以替补上场用于测试目的(认为没有DB后端集成测试。)在请求处理程序中然后可能放在响应:

Option(recordsFrom(database)) match{ 
    case Some(value) => OK ~> renderOpupt(value) 
    case None => //an error response or Pass 
} 

这样,你可能会沿着线的东西:

trait DBReqPlan{ 
    def dbReqCommand: RequestCommand[String] 

    def intent ={ 
    case req @ GET(Path(Seq(database :: Nil))) => dbReqCommand(req, database) 
    } 
} 

这是更容易测试反对和W ork与。

+0

感谢未经过滤的建议:)从这些答案看来,Scala并未提供在模式匹配情况下将别名应用于昂贵对象创建的机制。我猜这就是未过滤引入Pass的确切原因(即,在调用更高级的逻辑之后放弃匹配)...似乎是一个通用的要求... –

+1

@LawrenceWagerfield那么,这并不完全正确。你可以用自己的'unapply'来创建你自己的物品,然后你就可以匹配。我在Unfiltered之前完成了它,我称之为“路线”。然后你可以访问许多东西。也就是说,将DB访问作为路由的一部分,这仍然是一种相当糟糕的做法。身份验证可以在响应对象内处理,而不是。 – wheaties

+0

一个绝妙的主意(用于其他用例)! –