Scala error “value map is not a member of Double”

坚强是说给别人听的谎言 提交于 2019-12-24 16:00:18

问题


Explanation: I accepted gzm0's answer because it rocked!

@Eduardo did come in with a comment suggesting:

(for(i <- 10..20; j=runTest(i)) yield i -> j).toMap

which also lets me run build, he just never posted an answer and @gzm0 answer was conceptually AWESOME so I accepted it.

Once I get this other issue figured out relating to "can't call constructor" I will be able to test these out by actually running the program LOL

Question: I have an error in this expression, specifically how to fix it but more generally what am I missing about FP or Scala to make this mistake?

timingsMap = for (i <- powersList; j <- runTest(i)) yield i -> j

I am Writing my first Gradle/Scala project for a Analysis of Algorithms assignment. Scala is not part of the assignment so I am not using a homework tag. Except for my work with Spark in Java, I am brand new to Functional Programming I am sure that's the problem.

Here's a snippet, the full .scala file is on GitHub, is that OK or I will post the full program here if I get flailed :)

val powersList = List(10 to 20)

// create a map to keep track of power of two and resulting timings
var timingsMap: Map[Integer, Double] = Map()

// call the runTest function once for each power of two we want, from powersList,
// assign timingsMap the power of 2 value and results of runTest for that tree size
timingsMap = for (i <- powersList; j <- runTest(i)) yield i -> j

The error is: /home/jim/workspace/Scala/RedBlackTree4150/src/main/scala/Main.scala:36: value map is not a member of Double timingsMap = for (i <- powersList; j <- runTest(i)) yield i -> j

What I think I am doing in that timingsMap = ... line is get all the elements of powersList mapped onto i for each iteration of the loop, and the return value for runTest(i) mapped onto j for each iteration, and then taking all those pairs and putting them into timingsMap. Is it the way I am trying to use i in the loop to call runTest(i) that causes the problem?

runTest looks like this:

def runTest(powerOfTwo: Range): Double = {

    // create the tree here
    var tree = new TreeMap[Int, Double]

    // we only care to create a tree with integer keys, not what the value is
    for (x <- powerOfTwo) {
      // set next entry in map to key, random number
      tree += (x -> math.random)
    }

    stopWatchInst.start()

    // now go through and look up all the values in the tree,
    for (x <- powerOfTwo) {
      // get the value, don't take the time/overhead to store it in a var, as we don't need it
      tree.get(x)
    }

    // stop watch check time report and return time
    stopWatchInst.stop()
    val totalTime = stopWatchInst.elapsed(TimeUnit.MILLISECONDS)
    loggerInst.info("run for 2 to the power of " + powerOfTwo + " took " + totalTime + " ms")
    return totalTime
  }

Note: I've had a suggestions to change the j <- to = in j <- in this line: timingsMap = for (i <- powersList; j <- runTest(i)) yield i -> j

Another suggestion didn't like using yield at all and suggested replacing with (10 to 20).map...

The strange part is the existing code does not show an error in the IntelliJ editor, only breaks when I run it. The suggestions all give type mismatch errors in the IDE. I am really trying to figure out conceptually what I am doing wrong, thanks for any help! (and of course I need to get it to work!)


After trying gzm0 answer I am getting down the same road ... my code as presented doesn't show any type mismatches until I use gradle run ... whereas when I make the suggested changes it starts to give me errors right in the IDE ... but keep em coming! Here's the latest error based on gzm0s answer:

/home/jim/workspace/Scala/RedBlackTree4150/src/main/scala/Main.scala:37: type mismatch;
 found   : List[(scala.collection.immutable.Range.Inclusive, Double)]
 required: Map[Integer,Double]
  timingsMap = for (i <- powersList) yield i -> runTest(i)

回答1:


You want:

for (i <- powersList)
  yield i -> runTest(i)

The result of runTest is not a list, therefore you can't give it to the for statement. The reason that you get a bit of a strange error message, is due to how your for is desugared:

for (i <- powersList; j <- runTest(i)) yield i -> j

// turns into

powersList.flatMap { i => runTest(i).map { j => i -> j } }

However, the result of runTest(i) is a Double, which doesn't have a map method. So looking at the desugaring, the error message actually makes sense.

Note that my point about runTest's result not being a list is not really correct: Anything that has a map method that will allow the above statement (i.e. taking some kind of lambda) will do. However, this is beyond the scope of this answer.

We now have successfully created a list of tuples (since powersList is a List, the result of the for loop is a List as well). However, we want a Map. Luckily, you can call toMap on Lists that contain tuples to convert them into a Map:

val tups = for (i <- powersList) yield i -> runTest(i)
timingsMap = tups.toMap

A note aside: If you really want to keep the j inside the for-loop, you can use the equals sign instead of the left arrow:

for (i <- powersList; j = runTest(i)) yield i -> j

This will turn into:

powersList.map { i =>
  val j = runTest(i)
  i -> j
}

Which is what you want.



来源:https://stackoverflow.com/questions/34984070/scala-error-value-map-is-not-a-member-of-double

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!