4

Scalaプログラム(Axis jarなど)の依存関係として含まれているJarファイルにこのJavaクラスがあります。

class MyClass {
    private String[] someStrings;
    public String[] getSomeStrings() { return someStrings; }
}

私のScalaプログラムには、MyClassのMyClassインスタンスのインスタンスをScalaのプログラムに返すJavaAPIがあります。

val myInstance = JavaAPI.getInstanceOfMyClass()

次に、ScalaプログラムでsomeStrings配列を使用しようとしましたが、 nullです(正しく初期化されていなかったとしましょう)

for(str <- myInstance.getSomeStrings()) ...

したがって、これはNullPointerExceptionをスローします。

理解のためにそれを使用するために、NPEを適切に処理するようにオプションにラップできることがわかりました。

for(str <- Option[Array[String]](myInstance.getSomeStrings).getOrElse(Array[String]())

しかし、それは私にはうまく見えません。

nullであってもその値を取り、それをOptionにラップする暗黙のメソッドのように作成する方法はありますか?

implicit def wrapNull(a: Null): Option[Nothing] = None
implicit def wrapArray(a: Array[String]): Option[Array[String]] = Some(a)

だから私がするとき:

for(str <- myInstance.getSomeStrings())

NPEを取得できません

前もって感謝します!

4

3 に答える 3

4

編集:

Amapとalは、flatMap常に同じタイプを返す必要があり、そのタイプが呼び出されます。リストがある場合は、常にからリストを取得しmapます。オプションについても同じことが言えます。flatMapで2つのタイプを混在させようとすると、これはおそらく機能しません。どうしたら良い

Some(Array(1,2)).flatMap { x => 
  x.map { _ * 2 }
}

戻る?一部(2,4)は使用できません。したがって、タイプエラーが発生します。このため、のmap { map }代わりにネストを実行する必要がありflatMap { map }ます。

あなたの場合、それはこのように機能します:

case class A(b: B)
case class B(c: String)

val result = for(as <- Option(Array(A(B("foo")), A(B("bar"))))) yield {
  for(a <- as; b <- Option(a.b); c <- Option(b.c)) yield {
    c
  }
}

最初forはを取り、Option[Array[A]]を返しますOption[Array[String]]。ネストされたforは、を取り、Array[A]を返しますArray[String]。それらは両方ともモナド法を満たします。最後に、必要に応じて値をアンラップするようgetOrElseに安全に呼び出すことができます。result

オリジナル:

あなたはただすることができます

val result = Option(myInstance.getSomeStrings).map { x =>
  x.map { y =>
    // do stuff with strings
  }
}

また

val result = for(x <- Option(myInstance.getSomeStrings)) yield {
  x.map { y =>
    // do stuff with strings
  }
}

型推論のために型を記述する必要はなくgetOrElse、マップはに対して実行されないため、は必要ありませんNonegetOrElse値をアンラップする必要がある場合は、結果を単純に実行できます。

于 2012-04-12T21:31:32.240 に答える
3

のバージョンはそれほど悪いとは思いません(これは推測できるので、 aftergetOrElseを削除することで少し短くすることができます)。さらに簡潔なものが必要な場合は、次のように機能します。[Array[String]]Option

for (str <- Option(myInstance.getSomeStrings).flatten) ...

Optionがあるという事実を使用することもできます。foreach

for {
  strings <- Option(myInstance.getSomeStrings)
  str <- strings
} ...

yield以下のコメントでdrexinが強調表示されているため、ここでは使用できないことに注意してください。

またはあなたはポン引き MyClassすることができます:

implicit def withNullWrapper(c: MyClass) = new {
  def getSomeStringsOrNot() = Option(c.getSomeStrings).getOrElse(Array[String]())
}

for (str <- myInstance.getSomeStringsOrNot) ...
于 2012-04-12T21:41:37.737 に答える
2

簡単なルール:がある場合はnull、それをOption。それで:

for {
  array <- Option(myInstance.getSomeStrings)
  element <- array
  thingy <- Option(element.method)
} yield thingy

それだけではうまくいきません。のためにarray、それは複数の要素を返しますが、最初のジェネレーターはであるためOption、それは。を返しますOptionOptionこれらの2つの要素は不利です。複数の要素を返すことはできません。

問題を修正する最も簡単な方法はOption、をイテレータまたはコレクションに変換することです(好みに応じて)。このような:

for {
  array <- Option(myInstance.getSomeStrings).toSeq
  element <- array
  thingy <- Option(element.method)
} yield thingy

Option2番目に触れる必要はないことに注意してください。問題を引き起こしたのは最初のジェネレーターとしてのものでした。Option最初のジェネレーター以外は問題ありません。

于 2012-04-12T22:51:08.017 に答える