2012-12-18 9 views
9

JavaからScalaのスイッチャーとして、私は定期的に、私はそれが醜いとそれ本当には、Aのように見えると思う自分がScalaのベスト・プラクティス:簡単なオプション[]用法

val itemOpt: Option[Item] = items.get(coords) // "items" is something like a Map 
if (itemOpt.isDefined) { 
    val item = itemOpt.get 
    // do something with item, querying item fields a lot of times, for example 
    if (item.qty > 10) { 
    storeInVault(item.name, item.qty, coords) 
    } else { 
    storeInRoom(item) 
    } 
} 

のようなヌル取り扱いのものを書き換え見つけます

Javaでも醜いですが、少なくとも1行少なくなります。 Scalaでこのような単純なケースを処理するベストプラクティスは何ですか?私は既にとflattenのコレクションを処理して、Option[Stuff]のコレクションを知っています。私はデフォルト値を扱うためにgetOrElseを知っています。私は何かの夢:

items.get(coords).doIfDefined(item => 
    // do stuff with item 
) 

が、私はOption APIでそのような何も表示されません。

+4

これは役立つかもしれない:http://dibblego.wordpress.com/2008/01/16/scalaoption-cheat-sheet/は – dhg

答えて

12

を非常に人気のある使用パターン:それは定義されていた場合

val item: Option[Int] = None 
val result = item map (_ + 1) getOrElse 0 

ので、あなただけの値を変換するためにmapを使用しています。あなただけの値を使用したい場合

、それはOption内に格納され、その後、ちょうどforeachを使用する:あなたが実際に必要としないので、

item foreach { it => 
    println(it) 
} 

あなたが見ることができるように、Optionはまた、多くの収集方法をサポートしています新しいAPIを学ぶ。 1または0の要素を持つコレクションとして扱うことができます。

7

このあなたがする探しているものを達成する必要があります

items.get(coords).foreach{ item => 
    //do stuff 
} 
+6

また、単に(アイテム< - maybeItem)のために '内包するために使用します{.. 。} 'maybeItem'はあなたのオプションです。 –

+0

もっと倹約するには、注: 'items.get(coords)map {item => // ...' –

5

これを確認してください。Tony Morris post私がOptionを理解しようとしたとき、それは私を非常に助けました。あなたのコードは、このような方法で書き換えることがあります。

for (item <- items.get(coords)) { // "items" is something like a Map 
    // do something with item, querying item fields a lot of times, for example 
    if (item.qty > 10) { 
    storeInVault(item.name, item.qty, coords) 
    } else { 
    storeInRoom(item) 
    } 
} 
3

また、オプションifガードとのパターンマッチングに使用することができます。私はこのシナリオでそれを使用するのが好きで、読むのが簡単だと思います。

あなたのオプションがNoneではないので、あなたが最初にそれを行う、その後、あなたのitemOptがSomeNoneであるかどうかを確認するために検査するパターンマッチングを使用することができたときにオプションのmapだけで効果がありますので。

def shouldInVault(item: Item) = item.qty > 10 

val itemOpt: Option[Item] = items.get(coords).map(...) 

itemOpt match { 
    case Some(item) if shouldInVault(item) => storeInVault(item.name, item.qty, coords) 
    case Some(item) => storeInRoom(item) 
    case None => 
} 
関連する問題