1

Say I have some class B and some class A that I do not control:

class B
class A { def getB: B = ... }

Sometimes the result of getB is a valid B, and sometimes it is null. I have an optional A that I want to get an optional B out of. This is the "simplest" way I could figure out how to do it:

val a: Option[A] = ...
val b: Option[B] = a flatMap {x => Option(x.getB)}

I wanted to get rid of the named x, so I tried this, which isn't simpler:

val b: Option[B] = a map {_.getB} flatMap Option.apply

I tried composing _.getB with Option, and the only other thing I got to work was less simple:

val b: Option[B] = a flatMap {((x: A) => x.getB) andThen Option.apply _}

What is a simpler way? This seems like it would be a common enough problem that there is an elegant solution. What I would really like to have is something close to this, which is obviously not possible:

val b: Option[B] = a flatMap {Option(_.getB)}
Nate
  • 12,499
  • 5
  • 45
  • 60
  • 4
    "I wanted to get rid of the named x" Why do you want to get rid of it? It seems like the best option here. [Here is why you can't use `_`](http://stackoverflow.com/questions/1545168/scala-unexpectedly-not-being-able-to-ascertain-type-for-expanded-function) – evan.oman Feb 06 '17 at 21:13
  • If your concern is dealing with potential `null`s that should be `Option`s in a verbose way, over and over, consider wrapping `A` so that you can treat the problem at the source (by wrapping everything in `Option.apply`). – Michael Zajac Feb 07 '17 at 01:49
  • @evan058 I can live with `x`, it just feels like boilerplate. Thanks for the link; I was aware of the reason that particular syntax didn't work, I have just found as I've been learning Scala that it seems to be full of pleasant surprises, so I thought there might be one here as well. – Nate Feb 07 '17 at 14:24
  • Possible duplicate of [Scala Option map to another Option](http://stackoverflow.com/questions/14921591/scala-option-map-to-another-option) – zhelezoglo Feb 07 '17 at 17:08
  • @zhelezoglo Did you just seriously delete your answer and downvote my question because somebody downvoted you? Your answer taught me something, and I did not downvote it, even if it wasn't my accepted answer. – Nate Feb 07 '17 at 17:26
  • @Nate I never thought you downvoted my answer. But I think your question is misleading. You first said, you were looking for a way to get rid of _named x_, and posted a couple of ways you tried which were even longer then the original try. Then, 3 hours ago, you said, that _named x_ didn't matter in fact, and all you cared was avoiding boilerplate. But this question is a duplicate then. – zhelezoglo Feb 07 '17 at 17:37
  • @zhelezoglo You have misread what I wrote. I never said that named `x` didn't matter. If named `x` didn't matter, I wouldn't have asked the question. I said I could live with it even though I didn't like it. I accepted my fate, that there wasn't an even shorter way. I asked exactly the question I wanted to ask. – Nate Feb 07 '17 at 17:46
  • @Nate Could be. But it doesn't matter, since the question you asked was a duplicate. (I just wanted to explain what first made me think that it was not.) Checkout the answer to what you wanted to ask from here: http://stackoverflow.com/questions/14921591/scala-option-map-to-another-option It's without x, and without boilerplate. – zhelezoglo Feb 07 '17 at 17:59
  • @zheleoglo I didn't say the questions didn't have overlap. Their question was not "what [I] wanted to ask". As I said, I asked what I wanted to ask. To be clear, I'm not annoyed because you proposed a duplicate - just because you deleted your answer, which I thought was insightful. If you undelete your answer, I'll even upvote it. – Nate Feb 07 '17 at 19:31
  • @Nate To be clear, I'm sure it is a duplicate. But if you insist on that it's not(maybe I'm missing something), I will un-downvote it. This has nothing to do with my answer, you don't need to upvote it if you don't like it. – SO says, you have to edit your question first to let me re-vote. – zhelezoglo Feb 07 '17 at 20:48

1 Answers1

6

There's no way to make it more concise in-line, but you could use the "enrich my library" pattern to add your own functionality to A, such as a method called safeGetB that does what you want:

scala> :pa
// Entering paste mode (ctrl-D to finish)

class B
class A {
  def getB: B = null
}

implicit class RichA(a: A) {
  def safeGetB: Option[B] = Option(a.getB)
}

Some(new A()).flatMap(_.safeGetB)

// Exiting paste mode, now interpreting.

defined class B
defined class A
defined class RichA
res0: Option[B] = None
Eric
  • 1,114
  • 9
  • 13