Two questions about a simple recursive function

Hello,

I have two questions about the simple recursive function reported below (Scala 2.12.0-M5):

  1. why I have to add “.asInstanceOf[B]” on the line commented with “<==”? Is it related to type erasure? If I write just “Some(value)” the error is:

    type mismatch;
    found : value.type (with underlying type B)
    required: B

  2. once amended, another error appears:

    could not optimize @tailrec annotated method findPrefixNum1: it contains a recursive call not in tail position
    map.get(k) match {
    ^
    I am not able to figure out why this is the case: what is the operation after the recursive call?

    Thank you.


def findPrefixNum[B](find: B, prefix: String, map: Map[String, B]) : Option[B] = 
    {
        @annotation.tailrec
        def findPrefixNum1[B](num: Int) : Option[B] = 
        {
            val k = f"$prefix%s$num%d"
            map.get(k) match {
                case None =>
                    None
                case Some(value) => {
                    if (value == find)
                        Some(value.asInstanceOf[B]) // <==
                    else
                        findPrefixNum1(num + 1)
                }
            }
        }
        findPrefixNum1(1)
    }

You don’t want the second type param B, which shadows the first one.

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

def findPrefixNum[B](find: B, prefix: String, map: Map[String, B]) : Option[B] = {
  @annotation.tailrec
  def findPrefixNum1(num: Int) : Option[B] = map.get(f"$prefix%s$num%d") match {
    case None => None
    case x @ Some(find) => x
    case _ => findPrefixNum1(num + 1)
  }
  findPrefixNum1(1)
}

// Exiting paste mode, now interpreting.

findPrefixNum: [B](find: B, prefix: String, map: Map[String,B])Option[B]

The type of findPrefixNum is Option[B]. Option is implemented with sub-types Some[B] and None[Nothing]. If you create a Some with Some(value) the compiler can’t figure out you want an Option. It only knows the sub-type.

You can either use Option(value) which if value is not null will give you a Some(value): Option[B] of the desired type or you can switch the clauses of your if statement so that Option[B] is in the first clause and then your Some(value) can figure out it should be an Option (and not Some.type).

I’m not sure why you are getting the annotation.trailrec error. If this isn’t homework to implement a tailrec function you should look at Map#find which should simplify your code.