Scala 比较选项[T]的实例,避免使用None==None

Scala 比较选项[T]的实例,避免使用None==None,scala,Scala,昨天,我突然明白了,并且明白了人们如何以及为什么使用带有选项的“地图”方法来比较值。是的,我有点慢,对不起:) 我修改了这些非常好的链接,并提出了我想问的问题 在我的Lift webapp中,我有一些选项[User]和选项[Server]变量。我试图通过下面的检查来确定这个用户是否是这个服务器的管理员 if(user.map(_.id) == server.map(_.adminId)) 但我注意到,如果“user”为None,“server”也为None,则该检查成功,这对我来说并不好(

昨天,我突然明白了,并且明白了人们如何以及为什么使用带有选项的“地图”方法来比较值。是的,我有点慢,对不起:)

我修改了这些非常好的链接,并提出了我想问的问题

在我的Lift webapp中,我有一些选项[User]和选项[Server]变量。我试图通过下面的检查来确定这个用户是否是这个服务器的管理员

if(user.map(_.id) == server.map(_.adminId))

但我注意到,如果“user”为None,“server”也为None,则该检查成功,这对我来说并不好(如果其中任何一个为None,我希望该检查失败)。我可以添加user.isDefined条件,但我觉得有更正确的方法。你能告诉我如何用Scala的方式完成吗?

你可以用模式匹配(在本例中,这可能是最清晰的方式):

你也可以试着做一行,但我不建议你这样做,因为它非常模糊:

if ( user.flatMap{ user => server.map(_.adminId == user.id) }.getOrElse( false ) ) {
  // both ids are matching, handle this case here
}
else {
  // no match, handle this case here
}
最后,如果您只需要处理ID匹配的情况(如果不匹配,则什么也不做),那么使用a进行理解并不是很糟糕的选择(没有双关语):


for(user您可以使用

def isAdmin(server: Option[Server])(user: Option[User]): Boolean = (for {
    s <- server
    u <- user
  } yield (u.id == s.adminId)
).getOrElse(false)

为此,我习惯了
exists
/
contains
的组合

比较相同类型的两个选项时:

o1.exists(o2.contains)
在您的情况下,可以使用
map

user.map(_.id).exists(server.map(_.adminId).contains)
我们可以利用来使用元组用户/服务器的
选项

user zip server exists { case (user, server) => user.id == server.adminId }
其中
选项#zip
的行为为:

Some(User(id = "hello")) zip Some(Server(adminId = "world"))
// Some((User("hello"), Server("world")))
Some(User(id = "hello")) zip None        // None
None zip Some(Server(adminId = "world")) // None
None zip None                            // None

在哪里对由
zip

生成的可选元组应用谓词,一行程序可以简化一点:
user.exists(u=>server.exists(u.adminId==u.id))
正确,很好。我仍然认为一行程序在这里不是一个好主意,即使您的版本更简洁(因为意图仍然有些模糊)。
user.map(_.id).exists(server.map(_.adminId).contains)
user zip server exists { case (user, server) => user.id == server.adminId }
Some(User(id = "hello")) zip Some(Server(adminId = "world"))
// Some((User("hello"), Server("world")))
Some(User(id = "hello")) zip None        // None
None zip Some(Server(adminId = "world")) // None
None zip None                            // None