Scala Scripting Challenge: What’s Equivalent to this Groovy?

Inspired by Scala being in the Scripting Language Bowl, I wanted to take a look at Scala as a scripting language.

I’ve got this little Groovy code snippet:

(System.in.text =~ /\b((\p{Lu}\p{Ll}+)+)\b/).each {
  println "I found: ${it[0]}"
}

When run, it looks like this:

$ echo "
Foo
bAr
Baz
robert
Fischer
alicia
Weller
" | groovy ./CapitalInput.groovy
I found: Foo
I found: Baz
I found: Fischer
I found: Weller

What’s a nice Scala equivalent? Here’s the best I could come up with:

import scala.io.Source
 
val text = Source.fromInputStream(System.in).mkString("")
"""\b((\p{Lu}\p{Ll}+)+)\b""".r.findAllIn(text).foreach { found:String =>
    println("I found: " +  found)
}

That’s actually not too bad, but does anyone have anything better? Any obvious mistakes I’m making?

Related posts:

  1. Java Goes Scripting
  2. Feature or Bug, You Decide: Argument Reordering in Groovy
  3. Scala is Not a Functional Programming Language
  4. Bug Or Feature, You Decide: Groovy MetaClass Programming
  5. Two Interesting Events: Scala and a Story Slam
This entry was posted in Scala. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
  • Stevie Jobs

    Ew! I won’t be converting from Objective-C to Scala anytime soon.

  • http://www.smokejumperit.com Robert Fischer

    BTW, on the topic of using non-scripting languages for scripting, check out Brian’s old (but good) post: OCaml, the Scripting Language.

  • Paul Phillips

    The IO lib for this sort of task is woefully lacking, but it’s just a small matter of doing it, so it’s kind of silly to judge the language on the relatively high verbosity it takes to iterate over stdin. I’ll write something to make it a few characters one of these days.

    Off the top of my head,

    io.Source.fromInputStream(System.in).getLines map (_.trim) filter (x => !x.isEmpty && x(0).isUpperCase) foreach println

    … but again that can/will be way shorter sooner than later. (I don’t know for sure this does what yours does since you didn’t fully explain it and I didn’t immediately understand the regexp.)

  • http://www.smokejumperit.com Robert Fischer

    The goal is to grab all the capital words in the input, and then print out a line reading “I found: ${word}” for each capital word found. Your implementation seems to only catch words at the beginning of the line (assuming “trim” only trims off the ending carriage return/whitespace), and it doesn’t print out “I found” — I was disappointed to realize there wasn’t variable interpolation in Scala, and was hoping to be corrected there.

    String concatenation also got weird on me and forced me to do some explicit typing, so I suspect there might be a better way to do that.

    BTW, if I gave a mistaken impression about this, I’m sorry, but to be clear: I’m not passing any judgment on the language in this exercise. When I said “That’s actually not too bad”, I meant that my code example used fairly powerful structures and didn’t have much non-semantic boilerplate, but I’m definitely hopeful for something better. For instance, when I posted a Cedric’s Problem solution, I got some pretty impressive improvements over my attempt. I was hoping for a similar experience here.

  • Paul Phillips
    io.Source.fromInputStream(System.in).getLines.toList flatMap (_.split("\\s+")) filter (_(0).isUpperCase) foreach (x => println("I found: " + x))
  • http://www.smokejumperit.com Robert Fischer

    Interesting — I was getting errors on the “foreach” implementation which forced me to explicitly type it. Maybe because I was using {} instead of ()?

  • http://cleverlytitled.blogspot.com/ Mitch

    I don’t do any scripting with Scala, but I think that if I was going to I would develop a convenience/helper library to ease IO and text processing.

    For example, having something similar to this:

    object Scripting {
      import java.io.InputStream
      class RichInputStream(val in: InputStream) {
        import scala.io.Source
        def =~(re: String) = {
          re.r.findAllIn(Source.fromInputStream(in).mkString(""))
        }
      }
     
      implicit def enrichInputStream(in: InputStream) = {
        new RichInputStream(in)
      }
    }

    Allows you to treat input System.in much like the groovy version:

      System.in =~ """\b((\p{Lu}\p{Ll}+)+)\b""" foreach {
        found => println("I found: " + found)
      }
  • http://www.smokejumperit.com Robert Fischer

    Have you tested that code? If it works, my explicit-typing-required-by-{} theory is shot.

  • http://cleverlytitled.blogspot.com/ Mitch

    I tested a variation of this that made it more convenient to work around Eclipse’s limitation on piping.

      val s = "Blah foo Bar"
      new ByteArrayInputStream(s.getBytes) =~ """\b((\p{Lu}\p{Ll}+)+)\b""" foreach {
        found => println("I found: " + found)
      }

    I found: Blah
    I found: Bar

  • http://tristanhunt.com Tristan Juricek

    I followed Mitches ideas about building up some scripting sugar, but took a different approach, by “pimping” up both InputStream and String:

        object Scripting {
     
            import java.io.InputStream
     
            class RichInputStream( val in:InputStream ) {
                def text:String = io.Source.fromInputStream( in ).mkString( "" )
            }
     
            implicit def RichInputStream( in:InputStream ) = new RichInputStream( in )
     
            class SuperString( val wrapped:String ) {
                def words:Iterator[ String ] = """\w+""".r findAllIn wrapped
            }
     
            implicit def SuperString( s:String ) = new SuperString( s )
        }
     
     
        import Scripting._
     
        System.in.text.words.filter( _(0).isUpperCase ).foreach( found => println("I found: " + found ) )

    Something tells me I could build up a bunch of basic implicits like this rather rapidly.

  • Grover

    For the scripty stuff like this, just use Groovy. I think Scala is meant to be a replacement for the stuff people normally use Java for.

  • Categories