1

I have an Option, say O, which can either be None or may have some value inside. If it has some value, that value may have a flag, say f. My requirement is that if O is None, then I create an object, say of type MyEntity,but if O has a value with flag as true, I return Nil else I create instance of MyEntity with different value. Java code can be almost as:

if(O.isEmpty) {
  MyEntity("x")
} else {
  if(O.f) {
     Nil
   } else {
    MyEntity("y") // with different value
   }
}

I want to do this in functional style using HoFs provided in scala.Option. What would be best possible way of doing it? I could this so far :

if(O.isEmpty){
 MyEntity("x")
} else {
 Option.unless(O.exists(_.f))(MyEntity("y"))
}
Mandroid
  • 6,200
  • 12
  • 64
  • 134
  • The return that would be `Any` since that si the upper bound between `MyEntity` and `Nil` are you sure you want that? Also, it may help if you provide the definition of the value inside the **Option** - In any case, I would write this using **pattern matching** rather than higher order functions. – Luis Miguel Mejía Suárez Mar 24 '21 at 17:17
  • `Nil` is a name of an empty list. The proper Scala code would be returning `Option[MyEntity]` and the implementation would be something like `O.filterNot(_.f).map(_ => MyEntity("y"))` – Oleg Pyzhcov Mar 24 '21 at 17:17
  • @OlegPyzhcov that doesn't work since the value inside `MyEntity` is different for the empty case and the non-empty but no-flag case. – Luis Miguel Mejía Suárez Mar 24 '21 at 17:20

3 Answers3

1

I misread your question the first go round, so here is attempt #2

This is a great case for pattern matching:


val maybeMyEntity: Option[MyEntity] = option match {
    case Some(flagValue) if flagValue => None
//  case Some(true) => None (More concise, but does not highlight a handy feature)
    case Some(_) => Some(MyEntity("Y"))
    case None => Some(MyEntity("X"))
}

Pattern matching is very powerful.

Alternatively, mapping is another option:

mapping of an Option will only occur if its value is not empty, and flatMapping will remove the layer of Option added, from Option[Option[MyEntity]] to Option[MyEntity]

val result: Option[MyEntity] = if (option.isEmpty) {
    Some(Entity("X"))
} else {
    option.flatMap { flagValue =>
        if (flagValue) {
            None
        } else {
            Some(MyEntity("Y"))
        }
    }
}
  • 1
    `case Some(true)` would look better, also you are not wrapping in `Some` the correct answers. – Luis Miguel Mejía Suárez Mar 25 '21 at 12:48
  • @LuisMiguelMejíaSuárez could you clarify what you mean by "you are not wrapping in `Some` the correct answers"? I'm afraid I don't follow. – Randomness Slayer Mar 27 '21 at 23:20
  • But as to the `case Some(true)` would "look" better, that may be the case (looks "better" is very subjective, and clarity is paramount to stylistic choices imho), but I wanted to keep the structure as similar to that in the question posted. My hope was that the solution is very analogous to the attempt, and thus hopefully easier to understand. – Randomness Slayer Mar 27 '21 at 23:22
  • @LuisMiguelMejíaSuárez I see what you mean with the `Some`, I've corrected it. Thank you! – Randomness Slayer Mar 27 '21 at 23:26
0

As mentioned in the comments, Nil type is a List, and your expression should always return the same type (should really not be Any).

One possibility is to define a "sentinel" value for MyEntity, e.g.:

object MyEntity {
   val Nil = MyEntity("")
}

Now you can write:

   val result = O.fold(MyEntity("x")) { 
      case true => MyEntity.Nil
      case false => MyEntity("y")
   }
Dima
  • 39,570
  • 6
  • 44
  • 70
0
    case class AnOption(var flag: Boolean = true)
    
    case class MyEntities(name: String)
    
    val myOptionEntityCheck = (someOption: Option[AnOption]) => {
      someOption match {
        case None => Some(MyEntities("X"))
        case Some(aValue: AnOption) if aValue.flag => None
// OR   case Some(AnOption(true)) => None
        case Some(_) => Some(MyEntities("y"))
      }
    }
jwvh
  • 50,871
  • 7
  • 38
  • 64