Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
Scala for Data Science

You're reading from   Scala for Data Science Leverage the power of Scala with different tools to build scalable, robust data science applications

Arrow left icon
Product type Paperback
Published in Jan 2016
Publisher
ISBN-13 9781785281372
Length 416 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
 Bugnion Bugnion
Author Profile Icon Bugnion
Bugnion
Arrow right icon
View More author details
Toc

Table of Contents (22) Chapters Close

Scala for Data Science
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
1. Scala and Data Science FREE CHAPTER 2. Manipulating Data with Breeze 3. Plotting with breeze-viz 4. Parallel Collections and Futures 5. Scala and SQL through JDBC 6. Slick – A Functional Interface for SQL 7. Web APIs 8. Scala and MongoDB 9. Concurrency with Akka 10. Distributed Batch Processing with Spark 11. Spark SQL and DataFrames 12. Distributed Machine Learning with MLlib 13. Web APIs with Play 14. Visualization with D3 and the Play Framework Pattern Matching and Extractors Index

Appendix A. Pattern Matching and Extractors

Pattern matching is a powerful tool for control flow in Scala. It is often underused and under-estimated by people coming to Scala from imperative languages.

Let's start with a few examples of pattern matching before diving into the theory. We start by defining a tuple:

scala> val names = ("Pascal", "Bugnion")
names: (String, String) = (Pascal,Bugnion)

We can use pattern matching to extract the elements of this tuple and bind them to variables:

scala> val (firstName, lastName) = names
firstName: String = Pascal
lastName: String = Bugnion

We just extracted the two elements of the names tuple, binding them to the variables firstName and lastName. Notice how the left-hand side defines a pattern that the right-hand side must match: we are declaring that the variable names must be a two-element tuple. To make the pattern more specific, we could also have specified the expected types of the elements in the tuple:

scala> val (firstName:String, lastName:String) = names
firstName: String = Pascal
lastName: String = Bugnion

What happens if the pattern on the left-hand side does not match the right-hand side?

scala> val (firstName, middleName, lastName) = names
<console>:13: error: constructor cannot be instantiated to expected type;
found   : (T1, T2, T3)
required: (String, String)
   val (firstName, middleName, lastName) = names

This results in a compile error. Other types of pattern matching failures result in runtime errors.

Pattern matching is very expressive. To achieve the same behavior without pattern matching, you would have to do the following explicitly:

  • Verify that the variable names is a two-element tuple

  • Extract the first element and bind it to firstName

  • Extract the second element and bind it to lastName

If we expect certain elements in the tuple to have specific values, we can verify this as part of the pattern match. For instance, we can verify that the first element of the names tuple matches "Pascal":

scala> val ("Pascal", lastName) = names
lastName: String = Bugnion

Besides tuples, we can also match on Scala collections:

scala> val point = Array(1, 2, 3)
point: Array[Int] = Array(1, 2, 3)

scala> val Array(x, y, z) = point
x: Int = 1
y: Int = 2
z: Int = 3

Notice the similarity between this pattern matching and array construction:

scala> val point = Array(x, y, z)
point: Array[Int] = Array(1, 2, 3)

Syntactically, Scala expresses pattern matching as the reverse process to instance construction. We can think of pattern matching as the deconstruction of an object, binding the object's constituent parts to variables.

When matching against collections, one is sometimes only interested in matching the first element, or the first few elements, and discarding the rest of the collection, whatever its length. The operator _* will match against any number of elements:

scala> val Array(x, _*) = point
x: Int = 1

By default, the part of the pattern matched by the _* operator is not bound to a variable. We can capture it as follows:

scala> val Array(x, xs @ _*) = point
x: Int = 1
xs: Seq[Int] = Vector(2, 3)

Besides tuples and collections, we can also match against case classes. Let's start by defining a case representing a name:

scala> case class Name(first: String, last: String)
defined class Name

scala> val name = Name("Martin", "Odersky")
name: Name = Name(Martin,Odersky)

We can match against instances of Name in much the same way we matched against tuples:

scala> val Name(firstName, lastName) = name
firstName: String = Martin
lastName: String = Odersky

All these patterns can also be used in match statements:

scala> def greet(name:Name) = name match {
  case Name("Martin", "Odersky") => "An honor to meet you"
  case Name(first, "Bugnion") => "Wow! A family member!"
  case Name(first, last) => s"Hello, $first"
}
greet: (name: Name)String
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at £13.99/month. Cancel anytime
Visually different images