Perhaps the nicest thing about the OP Compiler project is that it's giving me the chance to really get sharp on Scala -- to get a sense of how to program the language idiomatically, the way it's supposed to be used, instead of just being transliterated Java. Occasionally, I write a few lines and marvel at how right and tight they are. Here's an example, which illustrates several elements. (None of which will be surprising to experienced functional programmers, but this stuff is new to me.)
Let's deal with the following problem. The OP Alpha listing consists of tables of a persona name, followed by date/award pairs. The problem at hand is that the "award" part often contains an attribution in parentheses, which is essentially noise -- a comment from my POV. For example:
Queen's Honor of Distinction (Jana IV)The bit in the parens is messing up parsing the award name, so I need to separate it out.
In many languages, that would take a fair number of lines, but in Scala it turns out to be essentially four (could be more concise, but this seems clearest):
Breaking that down:
val awardCommentRegex = new Regex("""^(.*?) \((.*)\)$""", "name", "comment")
val commentMatch = awardCommentRegex.findFirstMatchIn(award
val comment = commentMatch map (_.group("comment"))
val parsedAwardName = (commentMatch map (_.group("name"))).getOrElse(awardName)
- The input is "awardName" -- that's the field I'm trying to parse.
- The Regex is a fairly conventional regular expression; if it matches, it breaks the discovered groups into "name" and "comment".
- The assignment to commentMatch does the actual regular-expression matching. That returns Option[Match] -- that is to say, the result contains either "Some(m)", where m is the found match information, or "None". In general, idiomatic Scala uses Option frequently for cases like this, where a function might return a value and might not; it is much safer than returning nulls, and avoids the usual mess of inventing return codes.
- The assignment to comment does a "map", which basically keeps the exterior structure of a collection but changes the interior. In this case, it is transforming the Option[Match] to an Option[String], by extracting the matched comment if there was one. Again, if nothing was matched, it returns None.
- The assignment to parsedAwardName is similar, but this time I want to get a definite String out the end, not an Option[String]. So first I fetch an Option[String]. Then the getOrElse() method either fetches the guts of that Option -- the String itself -- or, if the value is None, returns the original awardName that I started with.
No deep message here -- I'm just enjoying the elegance of it. I've always thought that I would really like working in pure Scala, and so far that's proving correct. And bit by bit, I'm absorbing the functional-programming models, and coming to appreciate that they have evolved far enough to often be much more concise than the comparable imperitive code...