我的目的是在Scala中创建一个函数,它接受某种动态查询(类似于模式匹配中的case
表达式)并返回List
内的匹配实例。假设该列表由case class Person
的实例组成,这些实例具有不同类型的属性。该函数应该能够接受某些字段的动态值组合,并返回匹配的Person
s。我特意寻找一个干净的解决方案。使用这种函数的一种可能方法是将具有匿名类型的对象作为查询传递("模式"):
def find(?): List<Person> = { ? }
val matches = find(new { val name = "Name"; val gender = Gender.MALE })
理想情况下,我想制定一种传递条件的清洁方式,而不是具体的价值观,但它并不重要。因为我正在学习Scala,所以我不知道实现这种事情的所有技术。在C#中,我使用匿名类型(类似于上面的第二行代码)和dynamic
参数来实现类似的功能。 Scala中什么是干净而优雅的解决方案?
答案 0 :(得分:1)
我不确定这是否是你要找的,但让我们这样试试:
首先,我们将Person
定义为case class Person(name: String, gender: Gender.Value)
,其中Gender
是已定义的枚举。
然后我们创建一个Query
案例类,它具有相同的字段,但是默认为None
的选项,以及将查询与人进行比较的方法:
case class Query(name: Option[String] = None,
gender: Option[Gender.Value] = None){
def ===(person: Person) = check(person.name, name) &&
check(person.gender, gender)
private def check[T](field: T, q: Option[T]) = field == q.getOrElse(field)
}
不幸的是,在此解决方案中,===
必须为每个字段分别调用check
。让我们暂时不要这样做。也许这就足够了(因为,例如,字段列表不会改变)。
请注意,如果查询的选项为check
,则true
会返回None
,因此您不必通过查询的所有字段:
val q = Query(name = Some("Ann")) // the gender is not important
q === Person("Ann", Gender.FEMALE) // returns true
最后是find
方法:
def find(people: List[Person], query: Query) = people.filter(query === _)