如何在Scala中简洁地检查null或false?
在Groovy语言中,检查如何在Scala中简洁地检查null或false?,scala,null,Scala,Null,在Groovy语言中,检查null或false非常简单,例如: groovy代码: def some = getSomething() if(some) { // do something with some as it is not null or emtpy } 在Groovy中,如果some为null或为空字符串或为零数字等,则计算结果将为false。在Scala中测试null或false的类似简明方法是什么? 假设some只是Java类型的字符串,那么这部分问题的简单答案是什么 g
null
或false
非常简单,例如:
groovy代码:
def some = getSomething()
if(some) {
// do something with some as it is not null or emtpy
}
在Groovy中,如果some
为null
或为空字符串或为零数字等,则计算结果将为false
。在Scala中测试null
或false
的类似简明方法是什么?
假设some
只是Java类型的字符串,那么这部分问题的简单答案是什么
groovy中另一个更好的方法是:
def str = some?.toString()
这意味着如果
some
不是null
,那么some
上的toString
方法将被调用,而不是在some
为null
的情况下抛出NPE。Scala中有什么相似之处?在Scala中,您描述的表达式意味着在名为some
的对象上调用名为?
的方法。通常,对象没有名为?
的方法。您可以使用检查null
属性的?
方法创建自己对对象的隐式转换
implicit def conversion(x: AnyRef) = new {
def ? = x ne null
}
本质上,上述操作会将调用方法?
的任何对象转换为方法转换
右侧的表达式(其中没有?
方法)。例如,如果您这样做:
"".?
编译器将检测到字符串
对象没有?
方法,并将其重写为:
conversion("").?
如解释器所示(请注意,在对对象调用方法时,可以省略
):
所以你可以写:
if (some ?) {
// ...
}
或者,您可以使用?
方法创建到对象的隐式转换,如果参数不是null
,该方法将调用对象上的指定方法-执行以下操作:
scala> implicit def any2hm[T <: AnyRef](x: T) = new {
| def ?(f: T => Unit) = if (x ne null) f(x)
| }
any2hm: [T <: AnyRef](x: T)java.lang.Object{def ?(f: (T) => Unit): Unit}
scala> x ? { println }
!!
scala> y ? { println }
根据soc的答案(递归地)构建,您可以在上述示例中的
x
上进行模式匹配,以根据x
的类型细化?
的功能:您可以自己编写一些包装器或使用选项类型
不过,我真的不会检查null
。如果某个地方有一个null
,您应该修复它,而不是围绕它构建检查
基于axel22的答案:
implicit def any2hm(x: Any) = new {
def ? = x match {
case null => false
case false => false
case 0 => false
case s: String if s.isEmpty => false
case _ => true
}
}
编辑:这可能会使编译器崩溃或无法工作。我会调查。好吧,
布尔值
不能为空
,除非作为类型参数传递。处理null
的方法是将其转换为选项
,然后使用所有选项
内容。例如:
Option(some) foreach { s => println(s) }
Option(some) getOrElse defaultValue
由于Scala是静态类型,所以对象不能是“null、空字符串或零数字等”。您可能会传递一个
Any
,它可以是这些东西中的任何一个,但是您必须匹配每种类型,才能使用它做任何有用的事情。如果您发现自己处于这种情况,您很可能不是在使用惯用的Scala。您可能缺少的是,Scala中类似于getSomething
的函数可能不会返回null、空字符串或零数字。一个函数可能返回有意义的值,也可能不返回有意义的值,它将返回一个选项
——它将返回一些(有意义的值)
或无
然后,您可以检查这一点,并使用以下内容处理有意义的值
val some = getSomething()
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
因此,Scala没有尝试在返回值中对“failure”值进行编码,而是专门支持常见的“returnsomething或indicate failure”情况
话虽如此,Scala可与Java互操作,Java始终从函数返回空值。如果getSomething
是一个返回null的Java函数,那么有一个工厂对象将从返回的值中提取一些或没有
所以
。。。这很简单,我声称,不会对你进行NPE
其他答案是做一些有趣且惯用的事情,但这可能超出了您现在的需要。如果您使用,那么您可以将您的str
示例编写为
val str = ?:(some)(_.toString)()
它还允许您在不担心null
s的情况下进行链接(因此“合并”):
当然,这个答案只解决了问题的第二部分。您所要求的是Groovy、Ruby或CoffeeScript。对于这种情况,我通常使用我的
RichOption[T]
的?
方法,其定义如下
class RichOption[T](option: Option[T]) {
def ?[V](f: T => Option[V]): Option[V] = option match {
case Some(v) => f(v)
case _ => None
}
}
implicit def option2RichOption[T](option: Option[T]): RichOption[T] =
new RichOption[T](option)
scala> val xs = None
xs: None.type = None
scala> xs.?(_ => Option("gotcha"))
res1: Option[java.lang.String] = None
scala> val ys = Some(1)
ys: Some[Int] = Some(1)
scala> ys.?(x => Some(x * 2))
res2: Option[Int] = Some(2)
使用方法如下
class RichOption[T](option: Option[T]) {
def ?[V](f: T => Option[V]): Option[V] = option match {
case Some(v) => f(v)
case _ => None
}
}
implicit def option2RichOption[T](option: Option[T]): RichOption[T] =
new RichOption[T](option)
scala> val xs = None
xs: None.type = None
scala> xs.?(_ => Option("gotcha"))
res1: Option[java.lang.String] = None
scala> val ys = Some(1)
ys: Some[Int] = Some(1)
scala> ys.?(x => Some(x * 2))
res2: Option[Int] = Some(2)
使用以下几个答案中建议的模式匹配是一种很好的方法:
val some = Option(getSomething())
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
但是,有点冗长
我更喜欢以下方式映射一个选项
:
选项(getSomething())映射(something->doSomethingWith(something))
一个班轮,短,清晰
这样做的原因是,选项可以被看作是一个集合的特殊雪花,它包含零个元素或一个类型的元素,因为您可以将列表[a]映射到列表[B],所以您可以将选项[a]映射到选项[B]。这意味着,如果定义了选项[A]的实例,即它是某个[A],则结果是某个[B],否则为无。它真的很强大 问题是,如果将x
声明为Any
,它会为?
方法引入2个隐式转换到作用域中。如果其中一些是Java字符串类型,该怎么办?scala似乎缺乏groovy的简洁性。很抱歉,我没有两个答案都遵循,但感谢您的尝试。我只是在寻找简单的解决方案。@axel22:我提出了一个问题:SI-4724@amc:没问题。但我认为“简单的解决方案”是没有可能是null
或空或假的值。Scala已经有了很多处理潜在空值的支持—学习和使用它比使用隐式创建新的?
语法更好。一个原因是
scala> val xs = None
xs: None.type = None
scala> xs.?(_ => Option("gotcha"))
res1: Option[java.lang.String] = None
scala> val ys = Some(1)
ys: Some[Int] = Some(1)
scala> ys.?(x => Some(x * 2))
res2: Option[Int] = Some(2)
val some = Option(getSomething())
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}