最近我发现自己编写了数据库查询或简单的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
好。
我还可以使用其他技巧吗?
答案 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))
}
它更加通用和可扩展,但非常模糊。