Mark is a graph advocate and field engineer for Neo Technology, the company behind the Neo4j graph database. As a field engineer, Mark helps customers embrace graph data and Neo4j building sophisticated solutions to challenging data problems. When he's not with customers Mark is a developer on Neo4j and writes his experiences of being a graphista on a popular blog at http://markhneedham.com/blog. He tweets at @markhneedham. Mark is a DZone MVB and is not an employee of DZone and has posted 548 posts at DZone. You can read more from them at their website. View Full User Profile

Scala: Setting a default value

06.13.2011
| 4306 views |
  • submit to reddit

We wanted to try and generate a build label to use for the name of the artifacts archive that gets generated each time we run the build but wanted to default it to a hard coded value if the system property representing the build label wasn’t available.

In Ruby we would be able to do something like this:

buildLabel =  ENV["GO_PIPELINE_LABEL"] || "LOCAL"

There isn’t a function in Scala that does that so we initially ended up with this:

  def buildLabel() = [{ 
System.getenv("GO_PIPELINE_LABEL") match {
case null => "LOCAL"
case label => label
}
}

My colleague Mushtaq suggested passing the initial value into an Option like so…

def buildLabel() = {
Option(System.getenv("GO_PIPELINE_LABEL")).getOrElse("LOCAL")
}

…which I think is pretty neat!

I tried to see what the definition of an operator to do it the Ruby way would look like and ended up with the following:

class RichAny[A](value:A ) {                              
def || (default:A ) = { Option(value).getOrElse(default) }
}
implicit def any2RichAny[A <: AnyRef](x: A) = new RichAny(x)

Which we can use like so:

def buildLabel() = {
System.getenv("GO_PIPELINE_LABEL") || "LABEL"
}

I imagine that’s probably not the idiomatic Scala way to do it so I’d be curious to know what is.

From http://www.markhneedham.com/blog/2011/06/12/scala-setting-a-default-value/

Published at DZone with permission of Mark Needham, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Erik Post replied on Mon, 2011/06/13 - 6:05am

My 2c: nulls are not idiomatic in Scala to begin with. So I tend to convert my possibly null values to Options as early on as I can. Then you have your idiomatic '||' operators already available: orElse and getOrElse. They are a bit verbose perhaps, but I'd probably just stick with your colleague's Option(x) getOrElse defaultValue suggestion.

Erwin Mueller replied on Mon, 2011/06/13 - 2:30pm

I choose the Java way:

 buildLabel= System.getenv("GO_PIPELINE_LABEL")
if (buildLabel==null) { buildLabel = "LOCAL"; }

That way I can still understand it 2 weeks later.

I'm all for new languages and stuff, but do Scala developers have nothing better to do as to try to invent the most cryptic code possible?

Who can get more cryptic code?

class RichAny[A](value:A ) {                              
      def || (default:A ) = {  Option(value).getOrElse(default)  }
} 
implicit def any2RichAny[A <: AnyRef](x: A) = new RichAny(x)
def buildLabel() = { System.getenv("GO_PIPELINE_LABEL") || "LABEL" }

Cloves Almeida replied on Mon, 2011/06/13 - 7:24pm in response to: Erwin Mueller

Scala have an unnatural tendency to use symbols where words would be a better match.

Why not the SQLish:


import static myapp.NullUtils.*

...

buildLabel = coalesce(System.getenv("GO_PIPELINE_LABEL"),"LOCAL"); 

Erik Post replied on Thu, 2012/05/24 - 5:51pm in response to: Erwin Mueller

I hope you're not suggesting that x || y is cryptic. You can write the definition like this in Scala 2.10: 
 
implicit class RichAny[A](value:A) {                              
      def || (default:A ) = Option(value) getOrElse default
} 
 
It would be cool if you could explain what is cryptic about this, other than 'I am unfamiliar with basic Scala syntax for basic programming concepts and constructs such as method definitions, type polymorphism and type bounds'. 
If you like using a lot of characters, you could do:

implicit class RichAny[A](value: A) {                              
      def || (default: A) = {
          return Option(value).getOrElse(default)
      }
} 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.