Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-Assignment based on Collection

Edit

originally the question was "Collection to Tuple" as I assumed I needed a tuple in order to do variable multi-assignment. It turns out that one can do variable multi-assignment directly on collections. Retitled the question accordingly.

Original Have a simple Seq[String] derived from a regex that I would like to convert to a Tuple.

What's the most direct way to do so?

I currently have:

val(clazz, date) = captures match {
  case x: Seq[String] => (x(0), x(1))
}

Which is ok, but my routing layer has a bunch of regex matched routes that I'll be doing val(a,b,c) multi-assignment on (the capture group is always known since the route is not processed if regex does not match). Would be nice to have a leaner solution than match { case.. => ..}

What's the shortest 1-liner to convert collections to tuples in Scala?

like image 486
virtualeyes Avatar asked Dec 16 '22 04:12

virtualeyes


2 Answers

This is not an answer to the question but might solve the problem in a different way.

You know you can match a xs: List[String] like so:

val a :: b :: c :: _ = xs 

This assigns the first three elements of the list to a,b,c? You can match other things like Seq in the declaration of a val just like inside a case statement. Be sure you take care of matching errors:

Catching MatchError at val initialisation with pattern matching in Scala?

like image 62
ziggystar Avatar answered Jan 03 '23 02:01

ziggystar


You can make it slightly nicer using |> operator from Scalaz.

scala> val captures = Vector("Hello", "World")
captures: scala.collection.immutable.Vector[java.lang.String] = Vector(Hello, World)

scala> val (a, b) = captures |> { x => (x(0), x(1)) }
a: java.lang.String = Hello
b: java.lang.String = World

If you don't want to use Scalaz, you can define |> yourself as shown below:

scala> class AW[A](a: A) {
     |   def |>[B](f: A => B): B = f(a)
     | }
defined class AW

scala> implicit def aW[A](a: A): AW[A] = new AW(a)
aW: [A](a: A)AW[A]

EDIT:

Or, something like @ziggystar's suggestion:

scala> val Vector(a, b) = captures
a: java.lang.String = Hello
b: java.lang.String = World

You can make it more concise as shown below:

scala> val S = Seq
S: scala.collection.Seq.type = scala.collection.Seq$@157e63a

scala> val S(a, b) = captures
a: java.lang.String = Hello
b: java.lang.String = World
like image 28
missingfaktor Avatar answered Jan 03 '23 03:01

missingfaktor