Skip to content

Instantly share code, notes, and snippets.

@cloudbring
Created March 12, 2016 02:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cloudbring/bb77ad0b70e6005f0d1e to your computer and use it in GitHub Desktop.
Save cloudbring/bb77ad0b70e6005f0d1e to your computer and use it in GitHub Desktop.
// The unapply method of this object takes a string and returns an Option[String]
//   This means that the value being matched must be a string and the value extracted is also a string
scala> object SingleParamExtractor {
     | def unapply(v:String):Option[String] = if(v.contains("Hello")) Some("Hello") else None
     | }
defined module SingleParamExtractor
// this Will match since the extractor will return a Some object
scala> "Hello World" match { case SingleParamExtractor(v) => println(v) }
Hello
// this will not match and therefore an exception will be thrown
scala> "Hi World" match { case SingleParamExtractor(v) => println(v) }   
scala.MatchError: Hi World
                  at .(:7)
                  at .()
                  at RequestResult$.(:3)
                  at RequestResult$.()
                  at RequestResult$result()
                  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                  at sun.reflect.DelegatingMethodAccessorImpl.invok...
// This extractor converts the string to an int if possible.
scala> object ConvertToInt{         
     | def unapply(v:String):Option[Int] = try{ Some(v.toInt) } catch { case _ => None }
     | }
defined module ConvertToInt
scala> "10" match { case ConvertToInt(i) => println(i)}
10
// If you want to extract multiple elements you return an Option that contains a Tuple.  
//   In this example we divide the string into two parts if it has a space
scala> object MultipleParamExtractor {                                       
     |  def unapply(v:String):Option[(String,String)] = (v indexOf ' ') match {           
     | case x if (x>0) => Some ((v take x, v drop x+1))
     | case _ => None
     | }
     | }
defined module MultipleParamExtractor
scala> "hello everyone :)" match { case MultipleParamExtractor(one, two) => println(one,two) }
(hello,everyone :))
// Any object with a unapply method can be used it does not have to be defined as an object
// So if you have a class of extractors that needs to be parameterized you can 
// create a class and use instances of that class for matching
scala> class Splitter(sep:Char){
     | def unapply(v:String):Option[(String,String)] = (v indexOf sep) match {
     | case x if (x>0) => Some ((v take x, v drop x+1))
     | case _ => None
     | }
     | }
defined class Splitter
// Remember that we need the matching object start with an uppercase
// See http://daily-scala.blogspot.com/2009/09/case-sensitive-matching.html 
// for details
scala> val SplitOnComma = new Splitter (',')
SplitOnComma: Splitter = Splitter@15eb9b0d
// How cool now can create splitters for all sorts of things
scala> "1,2" match { case SplitOnComma(one,two) => println(one,two)}
(1,2)
// All extractors can also be used in assignments
scala> val SplitOnComma(one,two) = "1,2"                           
one: String = 1
two: String = 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment