Skip to content

Instantly share code, notes, and snippets.

@halfninja
Created March 28, 2012 15:31
Show Gist options
  • Save halfninja/2227348 to your computer and use it in GitHub Desktop.
Save halfninja/2227348 to your computer and use it in GitHub Desktop.
/*
* A selection of illustrative lines that describe a bit about how Scala does things
* and various parts of the language and/or library that you might find useful often.
*/
// val is similar to a final variable in Java - it can't be reassigned
val filename = "log.txt"
// var can be changed
var filename = "log.txt"
// type can be inferred, or you can be explicit
var filename:String = "log.txt"
// various collection types
val numbers = Seq(1,2,3)
val names = List("Ed","Fred")
// anonymous functions can be passed to methods, e.g. the map method
names.map(v => v.toUpperCase())
// returns List("ED","FRED"). A shorter version, where _ is a magic placeholder symbol
names.map(_.toUpperCase)
// also omitted the empty parens at the end, they're optional.
// parens and braces are usually interchangable too
// It's usually possible to omit even the dot before a method, which
// allows cool things like
val vegetables = Seq("Lettuce","Tomato")
val dressing = Seq("Vinegar","Oil")
val salad = vegetables ++ dressing
// What's happening on the last line is actually a method called "++", defined on most collections:
val salad = vegetables.++(dressing)
/** CLASSES */
// Class with constructor. If you don't have methods, you can leave out the body
class Dog(name:String)
// Make the name property readable
class Dog(val name:String)
// Extend a superclass and call its super-constructor
class Animal(legs:Int)
class Dog(val name:String) extends Animal(4)
// Let's add some methods. Fairly recognisable syntax.
// You can often omit things like brackets and braces for brevity.
class Dog(val name:String) {
def greet(yourName:String) {
val message = "Hello %s! My name is %s." format (yourName, name)
println(message)
}
def bark = println("woof!")
}
new Dog("Rex").greet("Ron")
// Hello Ron! My name is Rex.
/** OBJECTS */
// objects are a bit like singleton classes.
object Methods {
val get = "GET"
val put = "PUT"
// If you have an "apply" method on an object, you can call it like it's a method.
def apply() = new Dog("HTTP")
}
val webdog = Methods() // weird example
/** Pattern matching */
// Actually unrelated to regex (though regex is one thing it can be used for),
// it actually matches objects.
val fileDescription = myPage match {
case p:HtmlPage => "This is an HTML page"
case p:BinaryPage => "This is a file"
case _ => "Nobody knows what this is"
}
// some classes can be used to match inputs - it's a bit complicated to make your
// own but the Regex class is a good example of one that uses this technique
val NamePattern = """(\w+) (\w+)""".r // the r method makes a regex from a string
"Ronald Reagan" match {
case NamePattern(first, last) => println("Hello, "+first+"!")
case _ => println("Your name did not match my incredibly strict rules.")
}
/** JAVA INTEROP */
// Stuff mostly just works, but a few things you'll need.
// This import adds implicit conversions between Scala and Java collections
import collection.JavaConversions._
val myjavalist:java.util.List[String] = Seq("This","Gets","Converted")
// gets converted back on demand if you want to use Scala-style methods on your Java list
myjavalist.filter{_.length == 4}
// -> just the items with length == 4
// JavaBeans
// only really an issue if you use something like Spring that lives and breathes
// JavaBeans getters and setters.
// You could define the methods yourself, or you can use the handy @BeanProperty annotation:
@BeanProperty var name:String = _ // _ is a placeholder for the default value, in this case null.
/** THE OPTION CLASS */
// This isn't any special language feature, it's just a library class,
// but it makes use of some Scala features.
// It's intended to be a replacement for null values. Option[T] is a type which can either be
// Some(value) or None. It makes dealing with empty values easier.
// It helps to think of it as a sort of collection that contains either zero or one things. It even
// has a bunch of methods that are similar to the collection methods, like map().
// Using map(), you can grab properties out of it without worrying whether it's actually None -
// if it's None, it returns None.
val dog: Option[Dog] = findDogById(97)
val dogName = dog.map(_.name)
println(dogName.getOrElse("Nameless Dog"))
// It doesn't make null pointer exceptions impossible, it just makes them less likely,
// and makes code that's a bit easier to read than a brazillion "(if x != null)" statements.
// You can use the Option() method to wrap a regular variable - null becomes None.
Option(maybeNullDog) map { _.name } getOrElse ( "Anonydog" )
/** IMPLICIT */
// The "implicit" keyword can be used in a few places. The coolest place is on a method.
class AddNineable(num:Int) {
def addNine = num + 9
}
implicit def ToAddNineable(num:Int) = new AddNineable(num)
3.addNine // -> 12
// as you can see, the implicit conversion effectively allows you to mix in new methods to
// existing classes, by implicitly wrapping them in an adapter class. This is how the
// JavaConversions methods work.
// the other place you can use implicits is on variables and argument lists.
// Unless it makes the code hugely easier to use, it's best not to use it yourself
// as it can be confusing to have object magically passed in to methods.
// confusing example here: http://www.scala-lang.org/node/114
/** MANIFESTS */
// Manifests are a workaround for a limitation with the JVM. If you use generic types, the actual type
// is only available at compile time, and lost at runtime.
// This won't work:
def doesItHaveType[T](obj:Object) = obj instanceof T
// You can't do it in the JVM because it doesn't know what T is when you call it. Manifests are a class
// that Scala can implicitly provide to the method, containing information about T.
def doesItHaveType[T](obj:Object)(implicit manifest:Manifest[T]) = manifest.erasure.isInstance(obj)
// We've introduced two other Scala features here: implicit arguments, and multiple parameter lists.
// The second parameter list is implicit so its arguments are discovered by the compiler, and added.
// You can then call it like
val isString = doesItHaveType[String](myObject)
// This example is silly because we already have myObject.isInstance[String], but it illustrates the feature.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment