基于Option的条件方法链接

时间:2015-07-17 02:57:42

标签: scala

最近我发现自己编写了数据库查询或简单的Seq方法链,我想根据用户输入动态,例如:

def between(from: Option[DateTime], to: Option[DateTime]): Seq[MyObject] = {
    db.all() // let's say this returns Seq[MyObject]  
    /* Here I want to either restrict the upper/lower bounds with from/to if 
       they exist or take all the values otherwise */
}

如果我很懒,我会选择:

def between(from: Option[DateTime], to: Option[DateTime]): Seq[MyObject] = {
    if(from.isEmpty && to.isEmpty) db.all()
    else if(from.isEmpty) db.all().filter(_.date <= to.get)
    else if(to.isEmpty) db.all().filter(_.date >= from.get)
    else db.all().filter(_.date >= from.get && _.date <= to.get)
}

显然filter只是一个示例,当我想要take元素或基于选项的所有元素时,我遇到与n相同的问题。

但如果我有更多选项通过怎么办?在Scala中这样做的惯用方法是什么?

我可以使用模式匹配,但这与if/else没有太大区别?

我可以制作多个vals并执行from.map(...).getOrElse()但这会引入临时vals并且再次看起来不比if/else好。

我还可以使用其他技巧吗?

1 个答案:

答案 0 :(得分:2)

我认为这不是一个好的设计,因为它违反了between这个词的含义。

对于每种情况,我只有单独的方法,具有明确的语义:

def between(from: DateTime, DateTime)
def after(from: DateTime)
def before(to: DateTime)
def anytime()

否则,如果你真的想保持这种方式:

def between(from: Option[Date], to: Option[Date]) = {
 val datePredicate = (test: (Date,Date) => Boolean, date: Option[Date]) => (o: MyObject) => date.map(test(o.date, _)).getOrElse(true)
 val fromPredicate = datePredicate(_ >= _, from)
 val toPredicate = datePredicate(_ <= _, to)
 db.all().filter(x => fromPredicate(x) && toPredicate(x))
}

它更加通用和可扩展,但非常模糊。