Groovy言語では、次のようにnull
またはfalse
を確認するのは非常に簡単です。
グルーヴィーなコード:
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 type String?
また、Groovyのもう1つの優れた方法は次のとおりです。
def str = some?.toString()
つまり、some
がnull
ではない場合、toString
がsome
であった場合にNPEをスローする代わりに、some
のnull
メソッドが呼び出されます。 [$ var] _。 Scalaで似ているのは何ですか?
不足している可能性があるのは、ScalaのgetSomething
のような関数は、おそらく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")
}
したがって、戻り値に「失敗」値をエンコードしようとする代わりに、Scalaは、「意味のある何かを返すか、失敗を示す」ケースを具体的にサポートします。
そうは言っても、ScalaはJavaと相互運用可能で、Javaは常に関数からnullを返します。getSomething
がJava null、返された値からSomeまたはNoneを生成するファクトリオブジェクトがあります。
そう
val some = Option(getSomething())
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
...これは非常に単純で、私は主張し、あなたにNPEはしません。
他の答えは、おもしろくて慣用的なことをしているが、それはあなたが今必要としている以上のものかもしれない。
Boolean
は、型パラメーターとして渡されない限り、null
にはできません。 null
を処理する方法は、Option
に変換してから、すべてのOption
を使用することです。例えば:
Option(some) foreach { s => println(s) }
Option(some) getOrElse defaultValue
Scalaは静的に型であるため、Thingは "nullまたは空文字列またはゼロ番号などにはできません。Any
これはそれらのいずれでも構いませんが、とにかくそれを使って何か便利なことができるようにするには、それぞれのタイプで一致する必要があります。
Scalaでは、説明した式は、?
というメソッドがsome
というオブジェクトで呼び出されることを意味します。通常、オブジェクトには?
というメソッドがありません。 null
nessをチェックする?
メソッドを使用して、オブジェクトへの暗黙的な変換を作成できます。
implicit def conversion(x: AnyRef) = new {
def ? = x ne null
}
上記は、本質的に、メソッド?
を呼び出すオブジェクトをメソッドconversion
の右側の式に変換します(これはdoesを持ちます) ?
メソッド)。たとえば、これを行う場合:
"".?
コンパイラは、String
オブジェクトに?
メソッドがないことを検出し、次のように書き換えます。
conversion("").?
インタプリタで説明されています(オブジェクトのメソッドを呼び出すときに.
を省略できることに注意してください):
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
だからあなたは書くことができます:
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 }
それで、次のように書くことができます:
some ? { _.toString }
Socの答えに基づいて(再帰的に)ビルドすると、上記の例のx
のパターンマッチを実行して、x
のタイプに応じて?
の機能を絞り込むことができます。 :D
extemporeのヌルセーフ合体演算子 を使用する場合、次のようにstr
の例を書くことができます。
val str = ?:(some)(_.toString)()
また、null
sを気にせずに連鎖することができます(つまり、「結合」)。
val c = ?:(some)(_.toString)(_.length)()
もちろん、この答えはあなたの質問の2番目の部分のみを扱っています。
求めるのは、 Safe Navigation Operator(?。) Groovy、 and and gem of 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)
ラッパーを自分で作成するか、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
}
}
編集:これは、コンパイラをクラッシュさせるか、動作しないようです。調査します。
ここでいくつかの回答で提案されているパターンマッチングを使用するのは、素晴らしいアプローチです。
_val some = Option(getSomething())
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
_
しかし、少し冗長です。
私は次の方法でmap
とOption
を好む:
Option(getSomething()) map (something -> doSomethingWith(something))
ライナー1本、短く、透明。
その理由は、Optionが コレクションの種類 –リストのゼロ要素またはタイプの要素を1つだけ含むコレクションの特別なスノーフレークとして表示できるためです。List[A ]をリスト[B]に、オプション[A]をオプション[B]にマッピングできます。つまり、Option [A]のインスタンスが定義されている場合、つまりSome [A]の場合、結果はSome [B]になり、そうでない場合はNoneになります。本当にパワフルです!