Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should x._1,x._2... syntax be avoided?

Tags:

tuples

scala

I'm just starting out in Scala. I find myself using tuple variables a lot.

For example, here's some code I wrote:

/* Count each letter of a string and return in a list sorted by character  * countLetter("test") = List(('e',1),('s',1),('t',2)) */ def countLetters(s: String): List[(Char, Int)] = {   val charsListMap = s.toList.groupBy((c:Char) => c)   charsListMap.map(x => (x._1, x._2.length)).toList.sortBy(_._1) } 

Is this tuple syntax (x._1, x._2 etc) frowned upon by Scala developers?

like image 935
mawaldne Avatar asked Dec 09 '12 19:12

mawaldne


2 Answers

Are the tuple accessors frowned upon by Scala developers?

Short answer: no.

Slightly longer (by one character) answer: yes.

Too many _n's can be a code smell, and in your case the following is much clearer, in my opinion:

def countLetters(s: String): List[(Char, Int)] =   s.groupBy(identity).mapValues(_.length).toList.sortBy(_._1) 

There are lots of methods like mapValues that are specifically designed to cut down on the need for the noisy tuple accessors, so if you find yourself writing _1, etc., a lot, that probably means you're missing some nice library methods. But occasionally they're the cleanest way to write something (e.g., the final _1 in my rewrite).

One other thing to note is that excessive use of tuple accessors should be treated as a nudge toward promoting your tuples to case classes. Consider the following:

val name = ("Travis", "Brown")  println("Hello, " + name._1) 

As opposed to:

case class Name(first: String, last: String)  val name = Name("Travis", "Brown")  println("Hello, " + name.first) 

The extra case class definition in the second version buys a lot of readability for a single line of code.

like image 144
Travis Brown Avatar answered Sep 19 '22 18:09

Travis Brown


There is a better solution then x._N. Common way to work with tuples is pattern matching:

charsListMap.map{case (a, b) => (a, b.length)} 

You also may take a look at scalaz, there are some instruments for tuples:

import scalaz._ import Scalaz._  scala> (1, "a") bimap (_ + 2, _ + 2) res0: (Int, java.lang.String) = (3,a2)  scala> ('s, "abc") :-> { _.length } res1: (Symbol, Int) = ('s,3) 
like image 45
senia Avatar answered Sep 21 '22 18:09

senia