Scala Option и flatMap - PullRequest
       3

Scala Option и flatMap

1 голос
/ 05 января 2012

Я пытаюсь научиться работать «по пути Scala», поэтому мне было интересно, если следующий код, как это должно быть сделано в этом случае.

Итак, у меня есть сущности Пользователь и Компания (сопоставленные с картографом LiftWeb). Пользователь имеет currentUser, который содержит Опцию [Пользователь], а Компания имеет currentCompany, которая является Опцией [Компания]. Чтобы сравнить, является ли текущий пользователь владельцем текущей компании, я делаю что-то вроде:

Company.currentCompany.map{_.owner.get == User.currentUser.map{_.id.get}.openOr(-1) }.openOr(false)

Это работает, но почему-то это кажется довольно многословным. Это хорошо? Это не? Есть идеи получше? Спасибо!

Ответы [ 3 ]

10 голосов
/ 05 января 2012

Вы смотрели на использование для понимания ?Вы можете сделать что-то вроде следующего:

for(
  company <- Company.currentCompany.map{_.owner};
  user <- User.currentUser.map{_.id}
) yield (company == user).getOrElse(false)

Это вернет true, если Company.currentCompany имеет значение Some [значение], а User.currentCompany имеет значение Some [значение], а company.owner == user.id..

Я чувствую, что должен быть какой-то способ избавиться от этого getOrElse в конце и вернуть непосредственно развернутый логический код, надеюсь, кто-то еще сможет пролить свет на это!

6 голосов
/ 05 января 2012

Использование for-comp compition является окончательным решением, на самом деле ... или flatMap, но менее читабельным

Для вызова все генераторы связаны с использованием flatMap функции Monadic Option, кроме последнегокоторый сопоставлен (как любые for и yield).Вот хорошее слайд-шоу по нижним понятиям Monad

Таким образом, для понимания используется для прохождения всех шагов, пока они не закодированы в состоянии сбоя (None для Option).

Вот полный пример с четырьмя тестами (четыре основных случая) для каждой опции (для и flatMap)

case class User(id: String) {

}


object User {

  def currentUser(implicit me: Option[User]): Option[User] = me

}

case class Company(owner: Option[User]) {

}


object Company {

  def currentCompany(implicit myCompany: Option[Company]): Option[Company] = myCompany

}

object Test extends App {

  test1()
  test2()
  test3()
  test4()
  test5()
  test6()
  test7()
  test8()

  def test1() {
    implicit val me: Option[User] = None
    implicit val myCompany: Option[Company] = None

    val v: Boolean = (for {
      c <- Company.currentCompany
      u <- User.currentUser
      o <- c.owner if o.id == u.id
    } yield true) getOrElse false

    println(v)
  }

  def test2() {
    implicit val me: Option[User] = Some(User("me"))
    implicit val myCompany: Option[Company] = None

    val v: Boolean = (for {
      c <- Company.currentCompany
      u <- User.currentUser
      o <- c.owner if o.id == u.id
    } yield true) getOrElse false

    println(v)
  }

  def test3() {
    implicit val me: Option[User] = None
    implicit val myCompany = Some(Company(me))

    val v: Boolean = (for {
      c <- Company.currentCompany
      u <- User.currentUser
      o <- c.owner if o.id == u.id
    } yield true) getOrElse false

    println(v)
  }

  def test4() {
    implicit val me: Option[User] = Some(User("me"))
    implicit val myCompany = Some(Company(me))

    val v: Boolean = (for {
      c <- Company.currentCompany
      u <- User.currentUser
      o <- c.owner if o.id == u.id
    } yield true) getOrElse false

    println(v)
  }

  def test5() {
    implicit val me: Option[User] = None
    implicit val myCompany: Option[Company] = None


    val v:Boolean = Company.currentCompany.flatMap(c => User.currentUser.flatMap( u => c.owner.map(o => if (u.id == o.id) true else false))) getOrElse false

    println(v)
  }

  def test6() {
    implicit val me: Option[User] = Some(User("me"))
    implicit val myCompany: Option[Company] = None

    val v:Boolean = Company.currentCompany.flatMap(c => User.currentUser.flatMap( u => c.owner.map(o => if (u.id == o.id) true else false))) getOrElse false

    println(v)
  }

  def test7() {
    implicit val me: Option[User] = None
    implicit val myCompany = Some(Company(me))

    val v:Boolean = Company.currentCompany.flatMap(c => User.currentUser.flatMap( u => c.owner.map(o => if (u.id == o.id) true else false))) getOrElse false

    println(v)
  }

  def test8() {
    implicit val me: Option[User] = Some(User("me"))
    implicit val myCompany = Some(Company(me))

    val v:Boolean = Company.currentCompany.flatMap(c => User.currentUser.flatMap( u => c.owner.map(o => if (u.id == o.id) true else false))) getOrElse false

    println(v)
  }


}
0 голосов
/ 05 января 2012

Дано:

Case class user(name:String)
Case class company(owner:Option[User])

Val currentcompany=company(Some("Karl"))
Val currentuser=Some(user("Karl"))

Возможное решение:

currentcompany.foldLeft(false) { 
  case (a,b) => currentuser.isDefined && b.owner == currentUser.get
}
...