Я часто пишу код, который сравнивает два объекта и выдает значение, основанное на том, являются ли они одинаковыми или разными, в зависимости от того, насколько они различны.
Так что я мог бы написать:
val result = (v1,v2) match {
case (Some(value1), Some(value2)) => "a"
case (Some(value), None)) => "b"
case (None, Some(value)) => "b"
case _ = > "c"
}
Эти 2-й и 3-й случаи действительно одинаковы, поэтому я попытался написать:
val result = (v1,v2) match {
case (Some(value1), Some(value2)) => "a"
case (Some(value), None)) || (None, Some(value)) => "b"
case _ = > "c"
}
Но не повезло.
Я сталкиваюсь с этой проблемой в нескольких местах, и это только конкретный пример, более общий паттерн - у меня есть две вещи, и я хочу знать, соответствует ли один и только один из них некоторому предикату, поэтому хотел бы написать что-то вроде этого:
val result = (v1,v2) match {
case (Some(value1), Some(value2)) => "a"
case OneAndOnlyOne(value, v: Option[Foo] => v.isDefined ) => "b"
case _ = > "c"
}
Таким образом, идея заключается в том, что OneAndOnlyOne можно настроить с помощью предиката (в данном случае isDefined), и вы можете использовать его в нескольких местах.
Выше не работает вообще, так как в обратном направлении, предикат должен быть передан в экстрактор, а не возвращен.
Как насчет чего-то подобного?
val result = (v1,v2) match {
case (Some(value1), Some(value2)) => "a"
case new OneAndOnlyOne(v: Option[Foo] => v.isDefined )(value) => "b"
case _ = > "c"
}
с:
class OneAndOnlyOne[T](predicate: T => Boolean) {
def unapply( pair: Pair[T,T] ): Option[T] = {
val (item1,item2) = pair
val v1 = predicate(item1)
val v2 = predicate(item2)
if ( v1 != v2 )
Some( if ( v1 ) item1 else item2 )
else
None
}
}
Но это не компилируется.
Может кто-нибудь увидеть способ заставить это решение работать? Или предложить другое решение? Я, вероятно, делаю это более сложным, чем это:)