在Groovy语言中,检查null或更false喜欢它非常简单:
常规代码:
def some = getSomething()
if(some) {
// do something with some as it is not null or emtpy
}
Run Code Online (Sandbox Code Playgroud)
在Groovy中,如果some是null或是空字符串或是零数字等将评估为false.在Scala中null或falseScala 中测试的类似简洁方法是什么?这部分问题的简单答案是什么,假设some只是Java类型的String?
另外一个更好的方法是groovy:
def str = some?.toString()
Run Code Online (Sandbox Code Playgroud)
这意味着如果some不是null,则toString在方法some将被调用,而不是在壳体投掷NPE some是null.Scala有什么相似之处?
The*_*aul 51
您可能缺少的是,getSomethingScala 中的函数可能不会返回null,空字符串或零数字.一个可能返回一个有意义的值的函数,或者可能没有返回的函数Option- 它将返回Some(meaningfulvalue)或None.
然后,您可以检查这个并使用类似的方法处理有意义的值
val some = getSomething()
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
Run Code Online (Sandbox Code Playgroud)
因此,Scala没有尝试对返回值中的"失败"值进行编码,而是对常见的"返回有意义的或指示失败"的情况进行了特定支持.
话虽如此,Scala可与Java互操作,Java始终从函数中返回null.如果getSomething是返回null的Java函数,则有一个工厂对象将使返回值中的Some或None.
所以
val some = Option(getSomething())
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
Run Code Online (Sandbox Code Playgroud)
......我声称,这很简单,并且不会对你进行NPE.
其他答案正在做有趣和惯用的事情,但这可能比你现在需要的更多.
Dan*_*ral 35
好吧,Boolean不能null,除非作为类型参数传递.处理的方法null是将其转换为a Option,然后使用所有的Option东西.例如:
Option(some) foreach { s => println(s) }
Option(some) getOrElse defaultValue
Run Code Online (Sandbox Code Playgroud)
由于Scala是静态类型,因此不能是" null或空字符串或零数字等 ".你可以传递一个Any可以是任何这些东西,但是你必须匹配每种类型才能对它做任何有用的事情.如果你发现自己处于这种情况,你很可能没有做惯用的Scala.
axe*_*l22 19
在Scala中,您描述的表达式意味着在?被调用的对象上调用一个被调用的方法some.通常,对象没有调用的方法?.您可以使用?检查nullness 的方法创建自己的对对象的隐式转换.
implicit def conversion(x: AnyRef) = new {
def ? = x ne null
}
Run Code Online (Sandbox Code Playgroud)
上述的意志,在本质上,转换在其上调用方法的任何对象?到表达上的方法的右手侧conversion(其不具有?法).例如,如果您这样做:
"".?
Run Code Online (Sandbox Code Playgroud)
编译器将检测到一个String对象没有?方法,并将其重写为:
conversion("").?
Run Code Online (Sandbox Code Playgroud)
在解释器中说明(请注意,.在对象上调用方法时可以省略):
scala> implicit def any2hm(x: AnyRef) = new {
| def ? = x ne null
| }
any2hm: (x: AnyRef)java.lang.Object{def ?: Boolean}
scala> val x: String = "!!"
x: String = "!!"
scala> x ?
res0: Boolean = true
scala> val y: String = null
y: String = null
scala> y ?
res1: Boolean = false
Run Code Online (Sandbox Code Playgroud)
所以你可以写:
if (some ?) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
或者您可以使用一个?方法创建一个隐式转换为对象,如果参数不是,则调用对象上的指定方法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 }
Run Code Online (Sandbox Code Playgroud)
这样你就可以写:
some ? { _.toString }
Run Code Online (Sandbox Code Playgroud)
建立(递归地)关于soc的答案,你可以x在上面的例子中模式匹配,以?根据类型改进做什么x.:d
如果您使用extempore的null-safe coalescing运算符,那么您可以将您的str示例编写为
val str = ?:(some)(_.toString)()
Run Code Online (Sandbox Code Playgroud)
它还允许你链接而不用担心nulls(因此"合并"):
val c = ?:(some)(_.toString)(_.length)()
Run Code Online (Sandbox Code Playgroud)
当然,这个答案只涉及你问题的第二部分.
您可以自己编写一些包装器或使用Option类型.
我真的不会检查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
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:这似乎要么崩溃编译器或不起作用.我会调查.
你要求的是Groovy 的安全导航操作符(?.)和Ruby的gem,或者CoffeeScript 的存在操作符(?.)的访问者变体.对于这种情况,我通常使用?my的方法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)
Run Code Online (Sandbox Code Playgroud)
并使用如下
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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
43989 次 |
| 最近记录: |