2

2つの関数がfindUser(id:String):Option[User]ありfindAddress(user:User):Option[Address]、次のように呼び出されたとします。

for(user <-findUser(id); address <-findAddress(user))println(address)

ここで、これにエラーログを追加したいと思いますfor-comprehension。どちらかが見つからないlog(msg:String)場合は、関数を呼び出したいと思います。useraddress

for(user <-findUser(id)ifNone log( "user not found");
    アドレス<-findAddress(user)ifNone log( "アドレスが見つかりません"))
       println(アドレス)

関数のシグネチャを変更せずにそれを行うことはできますか?

4

3 に答える 3

3

Lift'sBoxは、ユースケースにより適したクラスです。ABoxは に似てOptionいますが、ok とエラーの 2 つの空の状態があります。次のように使用できます。

val addr = for {
  user <- findUser(id) ?~ "user not found"
  address <- findAddress(user) ?~ "address not found"
} yield address

address match {
  case Full(addr) => println(addr)
  case oops: Failure => println(oops.msg) // see Failure for more details
}

問題に関連するさまざまな提案については、このブログを参照してください。

于 2011-07-25T18:59:27.790 に答える
1

それはやり過ぎかもしれませんが、あなたが望んでいたものとかなり似ています;)

object Extensions {
  // You need a wrapper since Option is sealed
  class OptionWrapper[E](option: Option[E]) {
    def foreach[U](f: E => U) {
      option foreach f
    }
    def isEmpty = option.isEmpty
  }

  // Modification trait for OptionWrapper
  trait ErrorLogging[E] extends OptionWrapper[E] {
    abstract override def foreach[U](f: E => U) {
      if (isEmpty)
        println("error")
      else
        super.foreach(f)
    }
  }

  // Accessor for the new mixin
  def log[E](option: Option[E]) = new OptionWrapper(option) with ErrorLogging[E]
}

object TestingLogger extends App {
  case class User(address: String)
  def findUser(id: Int): Option[User] = if (id == 1) Some(User("address")) else None
  def findAddress(user: User): Option[String] = Some(user.address)

  import Extensions._

  for {
    user <- log(findUser(1)) // prints out address
    address <- log(findAddress(user))
  } println(address)

  for {
    user <- log(findUser(2)) // prints out error
    address <- log(findAddress(user))
  } println(address)
}

何が起こったのかわからない場合は、これを読んでください。

于 2011-07-25T19:21:37.797 に答える
1

多分

implicit def withIfNone[A](o: Option[A]) = new {
  def ifNone(action: => Unit) = { if (o == None) action; o }
}

また、オプションの代わりにどちらを使用するか (またはオプションをどちらかに変換するか) を検討することもできます。これは foreach (yield のない for) では機能しませんが、機能する可能性があります。

for(
  a <- option1.toRight("option1 missing").right; 
  b <- option2.toRight("option2 missing").right)
yield f(a,b)

次に、結果に対してパターンマッチを行うことができます

case Left(error) => log (error)
case Right(result) => // use result
于 2011-07-25T16:46:51.533 に答える