Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala newbie having troubles with tuples and closures

I have a List of tuples, and I'd like to traverse and get the value of each element.

this is the code:

scala> val myTuples = Seq((1, "name1"), (2, "name2"))
myTuples: Seq[(Int, java.lang.String)] = List((1,name1), (2,name2))

scala> myTuples.map{ println _ }
(1,name1)
(2,name2)
res32: Seq[Unit] = List((), ())

So far, so good, but

scala> myTuples.map{ println _._1 }
<console>:1: error: ';' expected but '.' found.
    myTuples.map{ println _._1 }

I also tried with:

scala> myTuples.map{ println(_._1) }
<console>:35: error: missing parameter type for expanded function ((x$1) => x$1._1)
          myTuples.map{ println(_._1) }

scala> myTuples.map{ val (id, name) = _ }
<console>:1: error: unbound placeholder parameter
       myTuples.map{ val (id, name) = _ }

scala> myTuples.map{ x => println x }
<console>:35: error: type mismatch;
 found   : Unit
 required: ?{val x: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method any2Ensuring in object Predef of type [A](x: A)Ensuring[A]
 and method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
 are possible conversion functions from Unit to ?{val x: ?}
              myTuples.map{ x => println x }

Declaring the variable, and using parentheses did the trick, but I'd like to know why the other options didn't work

these worked fine

myTuples.map{ x => println("id: %s, name: %s".format(x._1, x._2)) }

scala> myTuples.map{ x => println("id: %s, name: %s".format(x._1, x._2)) }
id: 1, name: name1
id: 2, name: name2
res21: Seq[Unit] = List((), ())

scala> myTuples.map{ x => val(id, name) = x; println("id: %s, name: %s".format(id, name)) }
id: 1, name: name1
id: 2, name: name2
res22: Seq[Unit] = List((), ())

scala> myTuples.map{ x => println(x._1) }

What happens to me, with my first steps with scala, is that insisting a little bit you get what you want, but you are unsure why the first options you tried didn't work...

like image 263
opensas Avatar asked Dec 21 '22 23:12

opensas


1 Answers

For the options that didn't work:

scala> myTuples.map{ println _._1 }

Short answer: In Scala, you always need to use parens around println's argument. Long answer: Scala only infers parenthesis for infix methods, meaning code of the forms object method argument gets interpreted as object.method(argument). No object is specified, so no parenthesis are inferred. You can see this directly by:

scala> println "Boom!"
<console>:1: error: ';' expected but string literal found.
       println "Boom!"
               ^

Next, myTuples.map{ println(_._1) }. It's not immediately clear to me why this doesn't work, since this should be equivalent to myTuples.map{ x => println(x._1) }, which works. As the answers to this question show, placeholder/partially applied method syntax applies to the smallest possible scope. So equivalent code would be myTuples.map { println(x => x._1) }. Since there's not enough information for scala to infer the type of x, you get a 'missing parameter type' error.

Regarding myTuples.map{ val (id, name) = _ }, placeholders are used in anonymous functions , whereas here you are initializing val's.

Then for myTuples.map{ x => println x }, you're also missing parens.

Finally, the option that worked for you myTuples.map{ x => println("id: %s, name: %s".format(id, name)) }, didn't actually work (look at the data it printed out). My guess if you had already defined id and name in the REPL, and those are the values being printed. Your working solutions work fine now.

My solution for doing what you're trying to do would be:

myTuples foreach {
  case (id, name) => printf("id: %s, name: %s\n", id, name)
}

or

myTuples foreach {
  x => printf("id: %s, name: %s\n", x._1, x._2)
}
like image 188
leedm777 Avatar answered Jan 06 '23 21:01

leedm777