a soft sea

Month

December 2010

2 posts

mime seating arrangments on airplanes

Recently I’ve been getting more into the idea of cloud hosting for tiny apps. Google App Engine is a perfect fitting glass shoe for applications written in java and other jvm languages of the future. The the world of scala we have sbt, and in the world of sbt we have plugins and in a world of repeatable tasks, we even have templates. Anyway… Even with a world of such luxury we sometimes can’t afford to make certain types of assumptions.

Living in a western world, it easy for most to people to live complacently with applications configured to use western only character sets. In the case of of applications serving string data outside those character encodings we have a few options. One of the most common encodings for multi-byte string content is utf-8. To enforce it, we were given weapons. Get into the habit of always putting the following line at the top of the head section of any rendered html.

<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

Recently I learned a new trick. As much as I despise java’s apparent fetish with xml configuration there is actually a handy block of code you can add to your web.xml config that should provide a suggestive hint to your servlet container to use a particular mime type for a given file extension when serving static content. It’s called mime-mapping. I think the original idea was to be able to provide a custom mime mapping for custom file extensions but you can also use it to override the default mime time for the most common string based file types of the interwebs. In doing so, you can have the oppurtunity encode the character encoding within the mime type as follows.

To reiterate.

before

> curl -I http://northeastscala.appspot.com
HTTP/1.1 200 OK
ETag: "zqO8fA"
Date: Wed, 15 Dec 2010 03:42:39 GMT
Expires: Wed, 15 Dec 2010 03:52:39 GMT
Cache-Control: public, max-age=600
Content-Type: text/html
Server: Google Frontend
Transfer-Encoding: chunked

after

> curl -I http://northeastscala.appspot.com
HTTP/1.1 200 OK
ETag: "MJtj8Q"
Date: Wed, 15 Dec 2010 03:43:23 GMT
Expires: Wed, 15 Dec 2010 03:53:23 GMT
Cache-Control: public, max-age=600
Content-Type: text/html; charset=utf-8
Server: Google Frontend
Transfer-Encoding: chunked

Don’t expect utf-8 content to be served when your app first jumps off the app engine plane. I did and it was kind of embarassing. It’s best to be safe and strap yourself in next to a mime you can trust.

Dec 14, 20101 note
#gae
magic match sticks and burnt fingers

First class pattern matching support is one of the many ways Scala stole my heart. I now use pattern matching as a superior refactoring and design tool in place of most every use case where I would historically insert another stray branch into a nest of ifs or query methods. Scala’s match keyword does what most languages switch or case keywords should do. Some may argue there’s too much magic behind it but once you understand that happens behind the curtains with unapply, most of that unfounded distrust goes away. For me, it’s just just the right amount of magic for me enjoy sticking my hand in the magician’s hat without the fear of uncertainty.

That doesn’t ways mean what my hand draws from the magicians hat is always what I expect.

Let’s look an extremely contrived example of using pattern matching.

def isRabbit(contents: String) =
  contents match {
    case "Buggs" => true
    case "Roger" => true
    case "Jessica" => false
    case _ => false 
 }

I’ve seen this trick enough to know that when I put my hand in, I have a pretty good idea of what I’ll get out depending on it’s contents. When see the magician stuff Buggs bunny into his hat before the show, I know I will pull out a rabbit. When I see the magician stuff Jessica Rabbit into his hat before the show, I know I will not being pulling out a rabbit. We’ve all been to that show before.

Now. We are good at extracting the hardcoded string values of our applications are’t we? Let’s extract thems that be causin all the code smell.

val buggs = "Buggs"
val roger = "Roger"
val jess = "Jessica"

def isRabbit(contents: String) =
  contents match {
    case buggs => true
    case roger => true
    case jess => false
    case _ => false 
 }

Can you guess what the contents of the hat will reveal when the magician puts “Roger” into the hat before the show? You sure? Okay. Now paste the code above into your nearest scala repl.

Ouch! Looks like you just got burnt. What’s with all this error: unreachable code business? Scala is supposed to prevent me from having buggs in my program, isn’t it?

Unbeknownst to me until recently is a little bit of knowledge that I hope to bestow upon the likes of you. So quiet the television and come sit close to the fire. Scala’s pattern matching engine will not treat lowercase variable names the same as will their value in match clauses. Don’t assume you can just use variables in the values’ stead without getting burnt. But, there is hope for sorry souls.

Scala has a convention for naming contants and so does English for its proper nouns: the first letter should be upper-cased.

Let’s revisit this ridiculous example so I can get to the point. Let’s rename those proper nouns using upper case identifiers.

val Buggs = "Buggs"
val Roger = "Roger"
val Jess = "Jessica"

def isRabbit(contents: String) =
  contents match {
    case Buggs => true
    case Roger => true
    case Jess => false
    case _ => false 
 }

Ah, ha! It totally works now. Why? Because scala treats pattern match case arguments that are identifiers as extractors and by convention an identifier starting with an uppercase letter is assumed to be a constant identifier. A constant can statically be compiled in bytecode because it will not change. A lowercase identifier by convention is not, and therefore is a lesser citizen and can be assumed to vary at runtime and cannot be statically compiled as a pattern match clause. So why do inline, hard coded strings work then? Duh. Strings are immutable and can not change so they can be statically compiled with the pattern match clause. With this information in hand, we should hopefully see why the semi-compiled version using lower case variable names errors out. The remaining case statements would never be reached and Scala thankfully lets us know this at compile time. One of the benefits you are afforded in a statically compiled language. At least this is my hypothesis :)

Before this magic show ends, I’d like to point out a lesser know feature of Scala’s syntax. Enter: the backtick! In some rare cases where you can just not stand to not use lower case variable names or when you get the itch to name something using a language keyword, you can wrap the identifier in a set of backticks. This will say to Scala: “Hey, I know this is wrong but give me a break. The magic business hasn’t been all that great lately”. Scala, being the nice language it is will reply: “Okay, I’ll let is one go for now”.

So if you absolutely wanted to use lower case identifiers in pattern match clauses, you can sneakily get away with the following.

def isRabbit(contents: String) =
  contents match {
    case `buggs` => true
    case `roger` => true
    case `jess` => false
    case _ => false 
 }

An surprisingly you can also get away with tomfoolery like this.

val `val` = "ue"
println(`val`)

the magician bows

I’d like to thank @boia01 and @jorgeortiz85 for some helpful insight on some frustration I had with an almost unrelated issue but with a totally related answer.

Enjoy the show!

Dec 4, 20103 notes
Next page →
2012 2013
  • January 1
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
2011 2012 2013
  • January
  • February
  • March 1
  • April 1
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
2010 2011 2012
  • January
  • February 1
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November 1
  • December 2
2010 2011
  • January
  • February
  • March 6
  • April 2
  • May 1
  • June
  • July 2
  • August 1
  • September
  • October
  • November
  • December 2