In Scala, you can perform pattern matching and work with regular expressions (regex) for string manipulation and validation.
Pattern Matching in Scala
Pattern matching in Scala is similar to switch-case in other languages but more powerful. It allows matching on types, constants, structures, and more.
How to perform pattern matching?
Ex:
def matchPattern(x: Int) = x match {
case 1 => "One"
case 2 => "Two"
case _ => "None of above"
}
x match: This is the pattern matching construct. It evaluates the value of x and compares it with the following cases.
case 1 => "One": Ifxis1, the function returns the string"One".case 2 => "Two": Ifxis2, the function returns the string"Two".case _ => "None of above": The underscore (_) acts as a wildcard that matches any value not explicitly handled in the previous cases. This is similar to thedefaultcase in other languages like Java’sswitch. Ifxis neither1nor2, it returns"None of above".
Example Usages:
- Input:
matchPattern(1)
Output:"One"
Explanation: Sincex = 1, it matches thecase 1and returns"One". - Input:
matchPattern(2)
Output:"Two"
Explanation: Sincex = 2, it matches thecase 2and returns"Two". - Input:
matchPattern(3)
Output:"None of above"
Explanation: Sincex = 3doesn’t match1or2, it falls to the wildcard (_) case and returns"None of above".
Ex : pattern matching can check against different types of data.
def matchTest(x: Any): String = x match {
case 1 => "One"
case "Scala" => "The Scala language"
case _: Int => "Some other integer"
case _ => "Unknown"
}
println(matchTest(1)) // Output: One
println(matchTest("Scala")) // Output: The Scala language
println(matchTest(42)) // Output: Some other integer
println(matchTest(true)) // Output: Unknown
Pattern matching with case classes
case classes :
- by default, the arguments are immutable, they are of type val. We can change them to var.
- case classes generate some additional functions automatically when you define a case class. It includes methods like equals, hashCode, toString.
case class Car(name:String, cost:Int)
val mercedes = new Car("Mercedes", 500000)
val bmw = new Car("BMW", 700000)
val jaguar = new Car("Jaguar", 1000000)
for (car <- List(mercedes,bmw,jaguar) ) {
car match {
case Car("Mercedes",500000) => println("Car is Mercedes, Congrats!")
case Car("BMW",700000) => println("Car is BMW, Waow!"
case Car(name,cost) => println("Car is" +name + "Cost is " + cost + "Thats Awesome!!!")
}
}
This Scala code demonstrates the use of case classes and pattern matching with instances of the Car case class. It iterates over a list of cars and matches each car’s properties to specific patterns to print custom messages.
Caris defined as a case class with two fields:name: A string representing the car’s name.cost: An integer representing the car’s cost.
Case classes in Scala provide useful features such as pattern matching, immutability, and automatic methods like equals, hashCode, and toString.
Three instances of the Car class are created:
mercedes: ACarobject with the name “Mercedes” and a cost of 500,000.bmw: ACarobject with the name “BMW” and a cost of 700,000.jaguar: ACarobject with the name “Jaguar” and a cost of 1,000,000.
The for loop iterates over a List containing the three cars (mercedes, bmw, jaguar).For each iteration, the car variable refers to the current Car object from the list.
- Pattern Matching (
match): For eachcarin the list, pattern matching is applied to check its name and cost.
Matching Cases:
case Car("Mercedes", 500000):- If the
carhas the name “Mercedes” and the cost is 500,000, it matches this case, and the message"Car is Mercedes, Congrats!"is printed.
- If the
case Car("BMW", 700000):- If the
carhas the name “BMW” and the cost is 700,000, it matches this case, and the message"Car is BMW, Waow!"is printed.
- If the
case Car(name, cost):- If the
cardoesn’t match the first two cases, it falls into this wildcard case, which matches anyCarobject. - The variables
nameandcostare extracted from the car, and the message"Car is [name] Cost is [cost] Thats Awesome!!!"is printed, where[name]and[cost]are the actual values from theCarobject.
- If the
Key Concepts:
- Case Classes: Simplify working with immutable data by providing built-in features like pattern matching.
- Pattern Matching: Allows checking the structure of data (here, the
Carcase class) and executing code based on the matched pattern. - Wildcard Case: Catches any unmatched patterns, with the ability to extract variable values from the matched data (e.g.,
name,cost).
Ex:
case class Success(message: String)
case class Failure(reason: String)
def handleResponse(response: Any): Unit = response match {
case Success(message) => println(s"Success: $message")
case Failure(reason) => println(s"Failure: $reason")
}
handleResponse(Success("All good!"))
handleResponse(Failure("Something went wrong"))
Pattern matching with case objects
A case object is a singleton object that has many of the same features as a case class. It is mainly used when you want a single instance of a class with pattern matching capabilities, and when you don’t need to maintain any state across different instances.
case object Stop
case object Start
def handleCommand(command: Any): String = command match {
case Start => "Starting the process"
case Stop => "Stopping the process"
case _ => "Unknown command"
}
println(handleCommand(Start)) // Output: Starting the process
println(handleCommand(Stop)) // Output: Stopping the process
Case objects are useful when you need to represent fixed, singleton values that can be used in pattern matching. For example, you could use case objects to represent different states or commands in a finite state machine or actor model.
case object Idle
case object Running
case object Stopped
def checkState(state: Any): Unit = state match {
case Idle => println("System is idle.")
case Running => println("System is running.")
case Stopped => println("System is stopped.")
case _ => println("Unknown state.")
}
checkState(Idle) // Output: System is idle.
checkState(Running) // Output: System is running.
When you need a set of fixed values, such as representing different days of the week or command statuses, case objects are an elegant solution in Scala (similar to enumerations in other languages).
case object Monday
case object Tuesday
case object Wednesday
def whichDay(day: Any): String = day match {
case Monday => "It's Monday."
case Tuesday => "It's Tuesday."
case Wednesday => "It's Wednesday."
case _ => "Unknown day."
}
println(whichDay(Monday)) // Output: It's Monday.
Regular Expressions
Regular expressions in Scala is adopted from Java. (Java Regular expressions adopted from Perl)
Scala provides support for regular expressions via the scala.util.matching.Regex class. You can use it to match, extract, or replace patterns in strings.
Basic Regex Operations
1. Creating a Regex
- Import
scala.util.matching.Regex - You have to create an object of class Regex
val pattern = new Regex("<whatever you want to match>")
(or)
val pattern = "<whatever you want to match>".r
In Scala, you can create a regex using the .r method on a string:
Ex:
import scala.util.matching.Regex // Always import this first
val pattern = new Regex("Hello") // Using the constructor for class Regex
val stringToFind = "Hello How are you? Hello Again" // String where you want to
search the pattern
pattern.findFirstIn(stringToFind) // Syntax to find the pattern in a given string. findFirstIn is the method which will only find the 1st instance of pattern
o/p : Option[String] = Some(Hello) // if you search for something that is not found, it will give you as None
// Find all matches
val matches = pattern.findAllIn(stringToFind).toList // findAllIn: Finds all matches.
println(matches) // Output: List(Hello, Hello)
Ex:
import scala.util.matching.Regex
val pattern = "Scala".r
val text = "Scala is awesome"
val result = pattern.findFirstIn(text)
println(result) // Output: Some(Scala)
.r — this is a method that is defined in a Regex class and it does nothing but calls the constructor.
.r: This is a method call on the string. In Scala, you can call methods on strings using dot notation. The r method is actually an implicit conversion that turns the string into a Regex object.
Matching for words in a String
val pattern: Regex = "([a-zA-Z]+)".r // A regex pattern that matches words
"([a-zA-Z]+)" matches one or more alphabetic characters (both lowercase and uppercase).
import scala.util.matching.Regex
val pattern: Regex = "([a-zA-Z]+)".r // A regex pattern that matches words
val input: String = "Hello Scala"
val matches = pattern.findAllIn(input) // Find all matches of the pattern in the input string
matches.foreach(println)
Matching for digits in a String
val pattern = "\\d+".r
(or)
val pattern = "[0-9]+".r // find all between 0 to 9 with 1 or more instance
"[0-9]+": This is a string literal that represents the regular expression pattern:
[0-9]is a character class that matches any single digit from 0 to 9.- The
+after[0-9]means “one or more occurrences of the preceding element”. - So
[0-9]+means “one or more digits”.
"\\d+": This is a string literal that represents the regular expression pattern:
\\dis an escaped version of\d. In regular expressions,\drepresents any digit (0-9).- The
+after\\dmeans “one or more occurrences of the preceding element”. - So
\\d+means “one or more digits”.
Both "[0-9]+".r and "\\d+".r are commonly used in Scala for matching digits. The choice between them often comes down to personal preference or team conventions.
val pattern = "\\d+".r
println(pattern.matches("123")) // true
println(pattern.matches("abc")) // false
println(pattern.matches("123abc")) // false
println(pattern.findFirstIn("The number is 42")) // Some(42)
val pattern = "[0-9]+".r
println(pattern.matches("123")) // true
println(pattern.matches("abc")) // false
println(pattern.matches("123abc")) // false
println(pattern.findFirstIn("The number is 42")) // Some(42)
var stringToFind = "My name is Harish and age is 10 and i study in standard 7"
val pattern = "[0-9]+".r // find all between 0 to 9 with 1 or more instance
(pattern findAllIn stringToFind).mkString(", ") // 10 7
(pattern findAllIn stringToFind).toArray // Array(10, 7)
--------------------------------------------------------------------
val pattern = "[0-9]+".r
val text = "I have 2 apples and 3 oranges."
// Find first match
println(pattern.findFirstIn(text)) // Output: Some(2)
// Find all matches
val matches = pattern.findAllIn(text).toList
println(matches) // Output: List(2, 3)
Matching for floating point values
val numberPattern = "\\d+(?:\\.\\d+)?".r
"\\d+(?:\\.\\d+)?": This is the string representation of the regular expression:
a. \\d+
\\drepresents any digit (0-9). It’s escaped with an extra\because it’s in a Scala string.+means “one or more occurrences of the preceding element”.- So
\\d+matches one or more digits.
b. (?:\\.\\d+)?
(?:...)is a non-capturing group. It groups elements but doesn’t create a capture group.\\.is an escaped period (dot). In regex, a dot usually means “any character”, so we escape it to mean a literal dot.\\d+again means one or more digits.- The
?at the end means “zero or one occurrence of the preceding group”.
Putting it all together:
- The pattern matches one or more digits, optionally followed by a decimal point and one or more digits.
- It will match integers (e.g., “42”) and decimal numbers (e.g., “3.14”).
Ex:
val numberPattern = "\\d+(?:\\.\\d+)?".r
println(numberPattern.matches("42")) // true
println(numberPattern.matches("3.14")) // true
println(numberPattern.matches("0.5")) // true
println(numberPattern.matches(".5")) // false (needs a digit before the decimal)
println(numberPattern.matches("abc")) // false
println(numberPattern.findAllIn("The price is $23.45 and the quantity is 5").toList)
// List(23.45, 5)
This pattern is particularly useful for tasks like:
- Validating numeric input
- Extracting numbers (both integers and decimals) from text
- Parsing financial data or scientific notation
It’s a flexible pattern that covers most common number formats, excluding things like scientific notation (e.g., 1e-10) or numbers with leading decimals (e.g., .5).
Case-insensitive matching of a specific word
val pattern = "(H|h)ello".r
This code creates a regular expression pattern that matches the word “Hello” or “hello”. Let’s examine each part:
val pattern: This declares an immutable value namedpattern."(H|h)ello": This is the string representation of the regular expression: a.(H|h): This is a capturing group that matches either an uppercase ‘H’ or a lowercase ‘h’.- The parentheses
()create a capturing group.The vertical bar|means “or” in regex. So this group matches either ‘H’ or ‘h’.
ello: This matches the literal string “ello”.- The parentheses
.r: This converts the string into aRegexobject.
Putting it all together:
- The pattern matches “Hello” or “hello”, allowing for variation in the first letter’s case.
- It will not match if any other letters are capitalized (e.g., “hEllo” would not match).
Here are some examples of how this pattern would behave:
val pattern = "(H|h)ello".r
println(pattern.matches("Hello")) // true
println(pattern.matches("hello")) // true
println(pattern.matches("HELLO")) // false
println(pattern.matches("Hello!")) // false (because of the exclamation mark)
println(pattern.matches("Hi")) // false
// Finding matches in a larger string
val text = "Hello world! hello there. Hellooo!"
pattern.findAllIn(text).foreach(println)
// Output:
// Hello
// hello
val stringToFind = "Hello How are you? hello Again"
(pattern findAllIn stringToFind).toArray // Array(Hello, hello)
This pattern is useful for:
- Case-insensitive matching of a specific word (in this case, “hello”)
- Extracting greetings from text where the capitalization may vary
- Validating user input where you want to allow for slight variations in capitalization
It’s a simple example of how you can use regex to create flexible matching patterns that account for common variations in text.
Validating Email Addresses
val emailRegex = """^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$""".r
This is a complex regular expression designed to match most common email address formats. Let’s analyze it piece by piece:
val emailRegex: This declares an immutable value namedemailRegex.- The
"""..."""syntax is a Scala multi-line string literal. It allows you to write the regex pattern without escaping special characters like backslashes. - The regex pattern:
^: Matches the start of the string.[a-zA-Z0-9._%+-]+: This matches the local part of the email (before the @):a-zA-Z0-9: Allows any alphanumeric character.._%+-: Allows these special characters.+: Means “one or more of the preceding character set”.
@: Matches the @ symbol literally.[a-zA-Z0-9.-]+: This matches the domain name:- Allows alphanumeric characters, dots, and hyphens.
\.: Matches a dot literally (for the top-level domain separator).[a-zA-Z]{2,}: Matches the top-level domain:a-zA-Z: Only alphabetic characters allowed.{2,}: At least two characters.
$: Matches the end of the string.
.r: Converts the string into aRegexobject.
This pattern aims to validate email addresses by ensuring they:
- Start with one or more allowed characters (alphanumeric and some special characters).
- Contain exactly one @ symbol.
- Have a domain name with allowed characters.
- End with a top-level domain of at least two alphabetic characters.
Here’s how you might use this regex:
val emailRegex = """^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$""".r
def isValidEmail(email: String): Boolean = emailRegex.matches(email)
println(isValidEmail("user@example.com")) // true
println(isValidEmail("user.name+tag@example.co.uk")) // true
println(isValidEmail("invalid.email@")) // false
println(isValidEmail("@invalid.com")) // false
println(isValidEmail("user@invalid")) // false
It’s worth noting that while this regex covers many common email formats, it may not catch all valid emails according to the full RFC specification, which is extremely complex. This regex is a good balance between accuracy and simplicity for most practical applications.
Regular expression with getOrElse function
The getOrElse method is often used with Options, which are commonly returned by regular expression operations.
getOrElse is a function that is used with Option types. It provides a way to return a default value in case the Option is None.
An Option[T] in Scala represents a value that could either be present (Some) or absent (None).
optionValue.getOrElse(defaultValue)
- If
optionValueisSome(value),getOrElsereturnsvalue. - If
optionValueisNone,getOrElsereturnsdefaultValue.
Ex:
val pattern = "(\\d+)".r
val text = "The number is 42"
val number = pattern.findFirstIn(text).getOrElse("No number found")
println(number) // Output: 42
val textWithoutNumber = "There is no number here"
val result = pattern.findFirstIn(textWithoutNumber).getOrElse("No number found")
println(result) // Output: No number found
-------------
val pattern = "Scala".r
val input = "I love programming"
// `findFirstIn` returns an Option, so we use getOrElse to provide a default message
val result = pattern.findFirstIn(input).getOrElse("No match found")
println(result) // Output: No match found
Using Regular expression with forEach
In Scala, regular expressions can be used to find patterns in strings, and the forEach method is often used to iterate over the matched results of a regular expression.
We use forEach to process each match.
import scala.util.matching.Regex
// Define a regular expression pattern to match words (one or more alphabetic characters)
val pattern: Regex = "([a-zA-Z]+)".r
// Input string containing words
val input: String = "Scala is a powerful language"
// `findAllIn` returns an Iterator over all matches
val matches = pattern.findAllIn(input)
// Use `forEach` to iterate over each match and print it
matches.foreach(println)
o/p:
Scala
is
a
powerful
language
Regex:"([a-zA-Z]+)"is a pattern that matches words (sequences of alphabetic characters).findAllIn: Finds all occurrences of the pattern in the string and returns anIterator[String]over the matches.forEach: Iterates over each match and applies a function to it (in this case,println).
The forEach method is applied to an iterator or collection and executes a function on each element.
// Define a regular expression pattern to match numbers
val numberPattern: Regex = """\d+""".r
// Input string with some numbers
val input: String = "There are 3 apples, 25 oranges, and 100 bananas"
// Find all numbers and process each one
numberPattern.findAllIn(input).foreach { matchFound =>
println(s"Found number: $matchFound")
}
o/p:
Found number: 3
Found number: 25
Found number: 100
- The
findAllInmethod returns anIteratorover matches, which you can iterate through usingforEach. forEachapplies a function to each match, making it easy to process or manipulate the matched data.
Regular expression meta character syntax
Here below is the list of metacharacter syntax:
| Subexpression | Matches |
|---|---|
| ^ | It is used to match starting point of the line. |
| $ | It is used to match terminating point of the line. |
| . | It is used to match any one character excluding the newline. |
| […] | It is used to match any one character within the brackets. |
| [^…] | It is used to match any one character which is not in the brackets. |
| \\A | It is used to match starting point of the intact string. |
| \\z | It is used to match terminating point of the intact string. |
| \\Z | It is used to match end of the whole string excluding the new line, if it exists. |
| re* | It is utilized to match zero or more appearances of the foregoing expressions. |
| re+ | It is used to match one or more of the foregoing expressions. |
| re? | It is used to match zero or one appearance of the foregoing expression. |
| re{ n} | It is used to matches precisely n number of appearances of the foregoing expression. |
| re{ n, } | It is used to match n or more appearances of the foregoing expression. |
| re{ n, m} | It is used to match at least n and at most m appearances of the foregoing expression. |
| q|r | It is utilized to match either q or r. |
| (re) | It is utilized to group the Regular expressions and recollects the text that are matched. |
| (?: re) | It also groups the regular expressions but does not recollects the matched text. |
| (?> re) | It is utilized to match self-reliant pattern in absence of backtracking. |
| \\w | It is used to match characters of the word. |
| \\W | It is used to match characters of the non-word. |
| \\s | It is utilized to match white spaces which are analogous to [\t\n\r\f]. |
| \\S | It is used to match non-white spaces. |
| \\d | It is used to match the digits i.e, [0-9]. |
| \\D | It is used to match non-digits. |
| \\G | It is used to match the point where the endmost match overs. |
| \\n | It is used for back-reference to occupy group number n. |
| \\b | It is used to match the word frontiers when it is out of the brackets and matches the backspace when it is in the brackets. |
| \\B | It is used to match non-word frontiers. |
| \\n, \\t, etc. | It is used to match the newlines, tabs, etc. |
| \\Q | It is used to escape (quote) each of the characters till \\E. |
| \\E | It is used in ends quoting starting with \\Q. |
Examples :
| Example | Description |
|---|---|
| . | Match any character except newline |
| [Rr]uby | Match “Ruby” or “ruby” |
| rub[ye] | Match “ruby” or “rube” |
| [aeiou] | Match any one lowercase vowel |
| [0-9] | Match any digit; same as [0123456789] |
| [a-z] | Match any lowercase ASCII letter |
| [A-Z] | Match any uppercase ASCII letter |
| [a-zA-Z0-9] | Match any of the above |
| [^aeiou] | Match anything other than a lowercase vowel |
| [^0-9] | Match anything other than a digit |
| \\d | Match a digit: [0-9] |
| \\D | Match a nondigit: [^0-9] |
| \\s | Match a whitespace character: [ \t\r\n\f] |
| \\S | Match nonwhitespace: [^ \t\r\n\f] |
| \\w | Match a single word character: [A-Za-z0-9_] |
| \\W | Match a nonword character: [^A-Za-z0-9_] |
| ruby? | Match “rub” or “ruby”: the y is optional |
| ruby* | Match “rub” plus 0 or more ys |
| ruby+ | Match “rub” plus 1 or more ys |
| \\d{3} | Match exactly 3 digits |
| \\d{3,} | Match 3 or more digits |
| \\d{3,5} | Match 3, 4, or 5 digits |
| \\D\\d+ | No group: + repeats \\d |
| (\\D\\d)+/ | Grouped: + repeats \\D\d pair |
| ([Rr]uby(, )?)+ | Match “Ruby”, “Ruby, ruby, ruby”, etc. |
Practical Intermediate stage examples
Consider these patterns :
"abl[ae]\\d+".r
This Scala regular expression pattern abl[ae]\\d+.r can be broken down as follows:
abl: Matches the exact stringabl.[ae]: This is a character class. It matches either the letteraor the lettereimmediately afterabl. So, it will matchablaorable.\\d: In Scala regex, the double backslash (\\) is used to escape special characters.\\dmatches a digit (equivalent to[0-9]in regex). This will match any single digit.+: The+quantifier means “one or more” of the preceding element. In this case, it refers to one or more digits (\\d+), meaning it will match one or more digits in sequence..r: In Scala, appending.rconverts the string into a regular expression object of typeRegex.
Example matches :
abla123
able45
abla9
"abl[ae]\\d*".r
The regular expression pattern abl[ae]\\d*.r in Scala can be broken down as below:
abl: Matches the exact stringabl.[ae]: Matches eitheraoreimmediately afterabl.\\d: Matches a digit ([0-9]).*: The*quantifier means “zero or more” of the preceding element. In this case, it refers to zero or more digits (\\d*), meaning it will match any number of digits, including no digits at all..r: Converts the string into a regular expression object in Scala.
Example matches :
abla (because * allows for zero digits)
able
abla123
able45
able9
"[Aa]bl[ae]\\d*".r
(or)
"(A|a)bl[ae]\\d*".r
[Aa]: This is a character class that matches either an uppercaseAor a lowercasea.(A|a): This is an alternation group, meaning it matches eitherAora. This achieves the same as[Aa].bl: Matches the exact stringblafter theAora.[ae]: A character class that matches eitheraoreimmediately afterbl.\\d*: Matches zero or more digits (\\drefers to digits, and*allows zero or more occurrences)..r: Converts the pattern into a regular expression object in Scala.
Examples :
Abla
able
abla123
Able456
able9
Both achieve the same result in this case, but the character class ([Aa]) is more concise and typically preferred for such simple cases. The alternation group ((A|a)) is more flexible for complex alternations (e.g., (cat|dog) matches either “cat” or “dog”).
Pattern to match numbers(optional negative signs & decimal parts)
"(-)?(\\d+)(\\.\\d*)?".r
(or)
"""(-)?(\d+)(\.\d*)?""".r
The Scala regular expression pattern (-)?(\\d+)(\\.\\d*)?.r is designed to match numbers, including optional negative signs and decimal parts. Here’s the breakdown:
1. (-)?:
- This part matches an optional minus sign (
-). - The
?means “zero or one occurrence,” so this part allows for numbers to be either positive or negative.
2. (\\d+):
\\d+matches one or more digits (\\drepresents a digit and+means “one or more”).- This part captures the integer part of the number.
3. (\\.\\d*)?:
\\.matches a literal dot (decimal point).\\d*matches zero or more digits following the decimal point (after the.).- The entire part
(\\.\\d*)?is optional (because of the?at the end), meaning the number can either have a decimal part or not.
4. .r:
- This converts the string into a regular expression object in Scala.
Summary:
This regular expression matches:
- An optional negative sign
- An integer part
- An optional decimal part
Examples :
123 (just an integer)
-123 (a negative integer)
123.45 (a positive decimal number)
-123.45 (a negative decimal number)
0.123 (a decimal number starting with zero)
-0.456 (a negative decimal number)
This pattern is useful for matching various kinds of numbers, including both integers and floating-point numbers.
Matching Groups
In Scala, regular expressions can capture parts of a matched string into groups. Groups allow you to extract specific sections from a match, which is particularly useful when you want to analyze different parts of a pattern separately.
Scala uses the parentheses () in a regular expression to define capturing groups. Once a group is captured, you can access it and use it for further processing.
val pattern = "([0-9]+) ([a-z]+)".r
val text = "123 abc"
val pattern(number, word) = text
println(s"Number: $number, Word: $word") // Output: Number: 123, Word: abc
Another example :
val Decimal = """(-)?(\d+)(\.\d*)?""".r
val Decimal(sign, integerpart, decimalpart) = "-1.23"
val stringToFind = "-1.5 divide by 5 is 3 is wrong"
for (Decimal(sign, integerpart, decimalpart) <- Decimal findAllIn stringToFind)
| println("Sign is " + sign + ", Integer Part is " + integerpart + ", Decimal Part is " +
decimalpart)
Sign is -, Integer Part is 1, Decimal Part is .5
Sign is null, Integer Part is 5, Decimal Part is null
Sign is null, Integer Part is 3, Decimal Part is null
val Decimal(sign, integerpart, decimalpart) = "-1.23"
- In this line, you’re using pattern matching with the regular expression
Decimalto extract components from the string"-1.23". - The expression
Decimal(sign, integerpart, decimalpart)is a deconstruction pattern that attempts to match the string against the regular expressionDecimal.
Step-by-Step Breakdown of the Pattern Matching:
"-1.23"is matched against the regular expression(-)?(\d+)(\.\d*)?.(-)?: The first capturing group,(-)?, matches the negative sign-, sosign = Some("-").(\d+): The second capturing group,(\d+), matches the integer part1, sointegerpart = "1".(\.\d*)?: The third capturing group,(\.\d*)?, matches the decimal part.23, sodecimalpart = ".23".
- After matching, the extracted values are assigned to the variables
sign,integerpart, anddecimalpart.
The regular expression object Decimal is applied to the string "-1.23". The string is deconstructed into its respective components based on the pattern. These components are assigned to the variables sign, integerpart, and decimalpart.