2015-07-17 3 views
1

Недавно я обнаружил, что пишут либо запросы к БД или простой 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 */ 
} 

Если бы я был ленив я d просто пойти с:

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 элементы или все они основаны на Option.

Но что делать, если у меня есть больше параметров? Каким будет идиоматический способ сделать это в Scala?

Я могу пойти с шаблоном, но это не сильно отличается от if/else?

я мог бы сделать несколько vals и сделать from.map(...).getOrElse() но вводит временный vals и снова не выглядит намного лучше, чем if/else.

Есть ли другие трюки, которые я мог бы использовать?

+0

Только вопрос, прежде чем пытаться ответить: есть ли смысл «между (Нет, Некоторые (...)» или «между (Нет, Нет)»? Я не думаю, что у него есть очевидная семантика и Я не знаю, что я должен ожидать, чтобы быть возвращенным как пользователь, поэтому я задаюсь вопросом, действительно ли этот метод имеет смысл вообще – Dici

+0

@ Dici Хорошо, да, как я пытался показать в примере, 'между (None, None)' будет возвращать все объекты, 'между (None, Some (to))' будут помещать только * верхнюю * границу, поэтому все объекты, которые старше, чем 'to'. –

+0

Да, так вы его реализовали, но это то, ожидать, т. е. это хороший API? – Dici

ответ

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)) 
} 

Это более общий и расширяемый , но очень неясный.

+0

, это на самом деле пропустит этот пункт. Прежде всего, я могу изменить имя (просто придумал что-то ради пример), во-вторых, мне нравится иметь одинарную конечную точку, для моих пользователей UI на самом деле проще, но не нужно делать какие-либо проверки, вводит ли пользователь что-то или нет. Как эти 4 метода отличаются от if/else? Мне нужно что-то делать. И последнее, но не в последнюю очередь это должен был быть общий вопрос, что, если я хочу иметь разные варианты фильтрации? Что-то, где я передаю X условия, завернутые в опцию? Мне нужно было бы создать метод для каждой возможности. –

+0

другое решение, которое мне больше нравится, посмотрит на него ;-) –

+0

Предлагаемое имя: «inInterval (lowerBound, upperBound)». Наличие одного из связанных (или даже обоих) отсутствующих звуков нормальное. –

Смежные вопросы