14

昨日、私は突然啓発され、人々が値を比較するために Option を使用して「マップ」メソッドを使用する方法と理由を理解しました。はい、私は少し遅いです、ごめんなさい:)

私はこれらの非常に素晴らしいリンクを修正し、私が尋ねたい質問に行き着きました。

http://twitter.github.com/effectivescala

http://blog.tmorris.net/posts/scalaoption-cheat-sheet

Lift webapp には、いくつかの Option[User] 変数と Option[Server] 変数があります。次のチェックで、このユーザーがこのサーバーの管理者であるかどうかを確認しようとしています

if(user.map(_.id) == server.map(_.adminId))

しかし、「ユーザー」が「なし」で「サーバー」も「なし」の場合、このチェックが成功することに気付きました。user.isDefined 条件を追加することもできますが、もっと正しい方法があると思います。Scalaの方法でそれを達成する方法を教えていただけますか?

4

4 に答える 4

26

パターン マッチングを使用してそれを行うことができます (この場合、これがおそらく最も明確な方法です)。

(user, server) match {
  case (Some(user), Some(server)) if user.id == server.adminId =>
    // both ids are matching, handle this case here
  case _ =>
    // no match, handle this case here
}

ワンライナーとして試すこともできますが、かなり難読化されているため、ここではお勧めしません。

if ( user.flatMap{ user => server.map(_.adminId == user.id) }.getOrElse( false ) ) {
  // both ids are matching, handle this case here
}
else {
  // no match, handle this case here
}

最後に、id が一致するケースのみを処理する必要がある場合 (一致しない場合は何もしない場合)、 for 内包表記を使用することはそれほど悪いオプションではありません (しゃれは意図されていません)。

for ( user <- user; server <- server if user.id == server.adminId ) {
  // both ids are matching, handle this case here
}
于 2013-01-28T19:05:31.117 に答える
3

あなたは理解のために使用することができます

def isAdmin(server: Option[Server])(user: Option[User]): Boolean = (for {
    s <- server
    u <- user
  } yield (u.id == s.adminId)
).getOrElse(false)

理解の結果、値を取得Option[Boolean]するかget、値falseがない場合 (オプションのいずれかが である場合、None要求したとおり)

なぜカレー?

メソッドをカリー化したので、特定のサーバーに対して関数を定義し、それを再利用して多くのユーザーをチェックできます

def isMyServerAdmin = isAdmin(Some(myServer)) _

isMyServerAdmin(Some(user1)) = true
isMyServerAdmin(Some(user2)) = false
isMyServerAdmin(None) = false
于 2013-01-29T10:14:57.837 に答える