Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Scala中简洁地检查null或false?_Scala_Null - Fatal编程技术网

如何在Scala中简洁地检查null或false?

如何在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

在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类型的字符串,那么这部分问题的简单答案是什么

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