A Scala approach to convert a multiline string to a list (Seq[String])

I saw the following image on this Twitter page:

and immediately became curious, “How can I create something like that Ruby %Q function in Scala, but where each line becomes a string in a list, i.e., a Seq[String]?”

A “Q” interpolator

Thanks to the help of Karsten — see the Comments section below — we can do something very similar in Scala. With his solution we can write code like this:

val list = Q"""
    http://angel.co/mile-high-organics
    http://angel.co/kindara
    http://angel.co/precog
    http://angel.co/pivotdesk
"""

His terrific solution was a combination of my “First attempt at a solution” shown below, and Scala’s string interpolation syntax.

The solution

Cutting right to the chase, his solution looks like this:

implicit class QHelper(val sc : StringContext) {
    def Q(args : Any*): Seq[String] = {
        val strings = sc.parts.iterator
        val expressions = args.iterator
        var buf = new StringBuffer(strings.next)
        while(strings.hasNext) {
        buf append expressions.next
        buf append strings.next
    }

    buf.toString.split("\n")
       .toSeq
       .map(_.trim)
       .filter(_ != "")
    }
}

My first attempt at a solution (the original/old code)

In my first attempt at a solution I couldn’t think of how to solve the problem without making the list of URLs a multiline string, so I ended up creating a Scala object with an apply method that converts a multiline string to a sequence:

object Q {

    def apply(s: String): Seq[String] = 
        s.split("\n")
        .toSeq
        .map(_.trim)
        .filter(_ != "")

}

Technically, that code converts a multiline String to a Seq[String].

I then tested that Q object with this little driver program:

object MultilineStringToList extends App {

    val list = Q("""
        http://angel.co/mile-high-organics
        http://angel.co/kindara
        http://angel.co/precog
        http://angel.co/pivotdesk
    """)

    list.foreach(println)

}

which printed out this:

http://angel.co/mile-high-organics
http://angel.co/kindara
http://angel.co/precog
http://angel.co/pivotdesk

That’s not quite as pretty as the Ruby code, but it’s close. IMHO, it’s also easier to read and type than this:

val list = List(
    "http://angel.co/mile-high-organics",
    "http://angel.co/kindara",
    "http://angel.co/precog",
    "http://angel.co/pivotdesk"
)

Summary

In summary, if you wanted to see how to convert a multiline string to a list/sequence in Scala, or otherwise wanted a Q class/function like this, I hope this is helpful. And again, thanks to Karsten for greatly improving my original code.