Search code examples
scalaapache-sparkhbase

Scala - How to return Option[String] instead of Any with pattern matching?


I wanted to get Sale objects from HBase concatenated with their HBase ids (a string representation of ImmutableBytesWritable) as Option[String].

First I've implemented processSales method so that it just returned all sales + hBase ids as shown below:

private def processSales (result: Result, hBaseId: String): Option[String] = {
    val triedSale: Try[Sale] = myThriftCodec.invert(result.getValue("binary", "object"))
    triedSale match {
      case Success(sale) => Some(hBaseId + sale)
      case _ => None
    }
  }

Now I want to return only those concatenated hBaseIds + Sales where Sales have metric_1 == null So I tried the following:

private def processSales (result: Result, hBaseId: String): Any = {
    val triedSale: Try[Sale] = myThriftCodec.invert(result.getValue("binary", "object"))
    triedSale match {
      case Success(sale) => Some(hBaseId + sale)
      case _ => None
    } 
triedSale match {
  case someSale => if (someSale.get.metric_1 = null) someSale.map(sale => hBaseId + sale)
}
  }

But it seems that I'm missing something here and the method returns Any even if I wrap this like this Option(hBaseId + sale).

What should I fix in my logic in order to return Option[String] with sales having metric_1 == null ?

UPD: Downvoting without pointing out the problems with my question doesn't make sense. It just totally demotivates seeking new knowledge.


Solution

  • You are missing the second option of the match case in your else, so it's returning Unit when the metric is not null, so Unit in one case, and Option(String) in another, the compiler guess that you want Any as return type

    What do you want to return when the metric_1 is not null? In this example you return the exact same input:

    triedSale match {
      case someSale => if (someSale.get.metric_1 = null) someSale.map(s => hBaseId + s) else someSale
    }  
    

    Or in a more elegant way you can do:

    triedSale match {
          case Success(metric_1) if metric_1 = null => Some(hBaseId + metric_1)
          case Success(metric_1) if metric_1 != null => triedSale
          case _ =>  None
     }
    

    EDIT

    As per the comments, you only want to return something when the metric_1 is null so here is the best solution as for my understanding:

    Also why are you pattern matching the same variable twice?

       triedSale match {
          case someSale => if (someSale.get.metric_1 = null) someSale.map(s => hBaseId + s) else None
        }  
    

    Or something like this:

    triedSale match {
          case Success(metric_1) if metric_1 = null => Some(hBaseId + metric_1)
          case _ =>  None
     }