Scala Comprehension Errors

815 views Asked by At

I am working on some of the exercism.io exercises. The current one I am working on is for Scala DNA exercise. Here is my code and the errors that I am receiving:

For reference, DNA is instantiated with a strand String. This DNA can call count (which counts the strand for the single nucleotide passed) and nucletideCounts which counts all of the respective occurrences of each nucleotide in the strand and returns a Map[Char,Int].

class DNA(strand:String) {

  def count(nucleotide:Char): Int = {
    strand.count(_ == nucleotide)
  }

  def nucleotideCounts = (
    for {
      n <- strand
      c <- count(n)
    } yield (n, c)
  ).toMap

}

The errors I am receiving are:

Error:(10, 17) value map is not a member of Int c <- count(n) ^

Error:(12, 5) Cannot prove that Char <:< (T, U). ).toMap ^

Error:(12, 5) not enough arguments for method toMap: (implicit ev: <:<[Char,(T, U)])scala.collection.immutable.Map[T,U]. Unspecified value parameter ev. ).toMap ^

I am quite new to Scala, so any enlightenment on why these errors are occurring and suggestions to fixing them would be greatly appreciated.

4

There are 4 answers

4
Akos Krivachy On BEST ANSWER

for comprehensions work over Traversable's that have flatMap and map methods defined, as the error message is pointing out.

In your case count returns with a simple integer so no need to "iterate" over it, just simply add it to your result set.

for {
  n <- strand
} yield (n, count(n))

On a side note this solution is not too optimal as in the case of a strand AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA count is going to be called many times. I would recommend calling toSet so you get the distinct Chars only:

for {
  n <- strand.toSet
} yield (n, count(n))
2
Ramón J Romero y Vigil On

A pipeline solution would look like:

def nucleotideCounts() = strand.groupBy(identity).mapValues(_.length)
3
elm On

In line with Akos's approach, consider a parallel traversal of a given strand (String),

strand.distinct.par.map( n => n -> count(n) )

Here we use distinct to gather unique items and construct each Map association in map.

1
user3720758 On

Another approach is

Map() ++ {for (n <- strand; c = count(n)) yield n->c}

Not sure why it's different than {...}.toMap() but it gets the job done!

Another way to go is

Map() ++ {for (n <- strand; c <- Seq(count(n))) yield n->c}