Scala Patterns and Extractors Guide

chapter 26 extractors n.w
1 / 26
Embed
Share

Learn how to define new patterns and use extractors in Scala to manipulate data efficiently and effectively. Explore examples of defining email patterns, utilizing extractors for pattern matching, and working with variables in Scala.

  • Scala Patterns
  • Extractors
  • Scala Guide
  • Pattern Matching
  • Scala Language

Uploaded on | 2 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.

E N D

Presentation Transcript


  1. Chapter 26 Extractors Kaitlin Dosch

  2. def isEmail(s: String): Boolean def domain(s: String): String def user(s: String): String s match { case Email(user, domain) => println(user + " AT " + domain) case _ => println("not an email address") if(isEmail(s)) println(user(s) + " AT " + domain(s)) else println("not an email address")

  3. Extractors Allow you to define new patterns for pre-existing types, where the pattern need not follow the internal representation of the type unapply and apply methods object Email{ def apply(user: String, domain: String) = user + "@" + domain def unapply(str: String): Option[(String, String)] = { val parts = str split "@" if(parts.length == 2) Some(parts(0), parts(1)) else None } }

  4. Extractors Whenever pattern matching encounters a pattern referring to an extractor object, it invokes the extractor's unapply method on the selector expression selectorString match { case Email(user, domain) => } Email.unapply(selectorString)

  5. unapply and apply unapply is called an extraction beacause it takes an element of the same set and extracts some of its parts apply is not required Called an injection because it takes some arguments and yields an element of a given set Email.unapply(Email.apply(user, domain)) Email.unapply(obj) match{ case Some(u,d) => Email.apply(u,d) } Some(user, domain)

  6. Patterns with one variable To bind N variables, an unapply would return an N-element tuple wrapped in a Some However, there is no one-tuple in Scala So, to return a one pattern element, the unapply method simply wraps the element itself in a Some object Twice { def apply(s: String): String = s + s def unapply(s: String): Option[String] = { val length = s.length / 2 val half = s.substring(0, length) if(half == s.substring(length)) Some(half) else None } }

  7. Patterns with zero variables In this case, the corresponding unapply method returns a boolean- true for success and false for failure object UpperCase { def unapply(s: String): Boolean = s.toUpperCase == s }

  8. def userTwiceUpper(s: String) = s match { case EMail(Twice(x @ UpperCase()), domain) => "match: " + x + " in domain " + domain case _ => "no match" } userTwiceUpper("DIDI@hotmail.com") //String = match: DI in domain hotmail.com userTwiceUpper("DIDO@hotmail.com") //String = no match userTwiceUpper("didi@hotmail.com") //String = no match

  9. Variable argument extractors How do you support vararg matching where patterns can have a varying number of sub-patterns? For this case, Scala lets you define a different extraction method specifically for vararg matching object Domain{ def apply(parts: String*): String = parts.reverse.mkString(".") def unapplySeq(whole: String): Option[Seq[String]] = dom match { case Domain("org", "acm") => println("acm.org") case Domain("com", "sun", "java") => println(java.sun.com") case Domain("net", _*) => println("a .net domain") } Some(whole.split("\\.").reverse.toSeq) }

  10. def isTomInDotCom(s: String): Boolean = s match { case EMail("tom", Domain("com", _*)) => true case _ => false } isTomInDotCom("tom@sun.com") //Boolean = true isTomInDotCom("peter@sun.com") //Boolean = false isTomInDotCom("tom@acm.org") //Boolean = false

  11. Extractors and Sequence Patterns You can access the elements of a list or an array using sequence patterns These sequence patterns are all implemented using extractors in the Scala standard library List() List(x, y, _*) List(x, 0, 0, _) package scala object List { def apply[T] (elems: T*) = elems.toList def unapplySeq[T](x: List[T]): Option[Seq[T]] = Some(x) } List() List(1, 2, 3)

  12. Extractors versus case classes Even though they are useful, case classes have one shortcoming: they expose the concrete representation of data Extractors break the link between data representations and patterns (Representation Independence) However, case classes have some advantages over extractors: 1. Much easier to set up and to define, and they require less code 2. Usually, lead to more efficient pattern matches than extractors 3. If they inherit from a sealed base class, the Scala compiler will check your pattern matches for exhaustiveness and will complain if some combination of possible values is not covered by a pattern

  13. Representation Independence Important advantage of extractors over case classes Extractors enable patterns that have nothing to do with the data type of the object that's selected on Important in open systems of large size because it allows you to change an implementation type used in a set of components without affecting clients of these components

  14. Regular Expressions Useful application of extractors Scala provides regular expressions through a library, but extractors make it much nicer to interact with them

  15. Forming regular expressions Regular Expression Meaning ab? An 'a', possibly followed by a 'b' . \d+ A number consisting of one or more digits represented by \d. import scala.util.matching.Regex val Decimal = new Regex("(-)?(\\d+)(\\.\\d*)?") [a-dA-D]\w* A word starting with a letter between a and d in lower or upper case, followed by a sequence of zero or more "word characters" denoted by \w. (-)?(\d+)(\.\d*)? A number consisting of an optional minus sign, followed by one or more digits, optionally followed by a period and zero or more digits. val Decimal = """(-)?(\d+)(\.\d*)?""".r

  16. Searching for regular expressions Search for occurences of a regular expression in a string using several different operations: 1. regex findFirstIn str 2. regex findAllIn str 3. regex findPrefixOf str val input = "for 1.0 to 99 by 3" for(s <- Decimal findAllIn input) println(s) Decimal findFirstIn input Decimal findPrefixOf input

  17. Extracting with regular expressions Every regular expression in Scala defines an extractor The extractor is used to identify substrings that are matched by the groups of the regular expression val Decimal(sign, integerpart, decimalpart) = "-1.23" val Decimal(sign, integerpart, decimalpart) = "1.0" for(Decimal(s, i, d) <- Decimal findAllIn input) println("sign: " + s + ", integer: " + i + ", decimal: " + d)

  18. Chapter 27 Annotations

  19. Why have annotations? There are many things you can do with a program other than compiling and running it (meta- programming tools): 1. Automatic generation of documentation 2. Pretty printing code so that it matches your preferred style 3. Checking code for common errors 4. Experimental type checking Annotations can improve the previously listed tools by: 1. A documentation generator could be instructed to document certain methods as deprecated 2. A pretty printer could be instructed to skip over parts of the program that have been carefully formatted 3. A checker for non-closed files could be instructed to ignore a particular file that has been manually verified to be closed 4. A side-effect checker could be instructed to verify that a specified method has no side effects

  20. Syntax of annotations Annotations have a richer general form: @annot(exp1, exp2, ) import annotation. @deprecated def bigMistake() = //... class strategy(arg: Annotation) extends Annotation class delayed extends Annotation @strategy(@delayed) def f() = {} (e: @unchecked) match { // non-exhaustive cases } @strategy(new delayed) def f() = {}

  21. Standard annotations They are for features that are used widely enough to merit putting in the language specification, but that are not fundamental enough to merit their own syntax

  22. Deprecation @deprecated def bigMistake() = //... @deprecated("use newShinyMethod() instead") def bigMistake() = //...

  23. Volatile fields Concurrent programming does not mix well with shared mutable state @volatile Informs the compiler that the variable in question will be used by multiple threads

  24. Binary Serialization A serialization framework helps you convert objects into a stream of bytes and vice versa Scala does not have a serialization framework, so you should use a framework from your underlying platform Scala does provide two annotations that are useful for a variety of frameworks: 1. @SerialVersionUID(1234) The framework should store this number in the generated byte stream When you later reload that byte stream and try to convert it to an object, the framework can check that the current verison of the class has the same version number as the version in the byte stream 2. @transient

  25. Automatic get and set methods Scala code normally does not need explicit get and set methods for fields Scala provides @scala.reflect.BeanProperty

  26. Tailrec, Unchecked, and Native methods @tailrec would typically be added to a method that needs to be tail recursive @unchecked is interpreted by the compiler during pattern matches, telling the compiler to not worry if the match expression seems to leave out some cases @native informs the compiler that a method's implementation is supplied by the runtime rather than in Scala code

Related


More Related Content