Skip to main content

Swift Expression Pattern

In Swift pattern matching, an expression pattern matches against values by evaluating an expression. This powerful feature allows you to compare values against expressions in switch statements and other pattern-matching contexts. In this lesson, we'll explore how expression patterns work and how they can make your code more elegant and concise.

Introduction to Expression Patterns

An expression pattern represents a value that can be compared with the input value using Swift's pattern matching operator (~=). This allows you to match against values in creative and flexible ways.

Expression patterns are particularly useful when:

  • You need to match against computed values
  • You want to check if a value falls within a range
  • You're implementing custom pattern matching behavior

Basic Expression Pattern Usage

Let's start with a simple example of an expression pattern in a switch statement:

swift
let value = 42

switch value {
case 0:
print("Zero")
case 1...50:
print("Between 1 and 50")
case 100:
print("One hundred")
default:
print("Some other value")
}

Output:

Between 1 and 50

In this example, 1...50 is an expression pattern that represents a range. The ~= operator is used implicitly to check if value is contained within this range.

How the Pattern Matching Operator Works

Behind the scenes, Swift uses the ~= operator for pattern matching. This operator is defined for many standard types, and you can also overload it for custom types.

The basic form is:

swift
pattern ~= value

For example, with a range:

swift
let matchResult = (1...50) ~= 42  // true
print(matchResult)

Output:

true

Common Expression Patterns

Range Patterns

Range patterns are among the most commonly used expression patterns:

swift
let score = 85

switch score {
case 0..<60:
print("Failed")
case 60..<70:
print("D grade")
case 70..<80:
print("C grade")
case 80..<90:
print("B grade")
case 90...100:
print("A grade")
default:
print("Invalid score")
}

Output:

B grade

Type Casting Patterns

You can use the is and as patterns to check and cast types:

swift
let item: Any = "Hello, Swift!"

switch item {
case is String:
print("This is a string")
case is Int:
print("This is an integer")
case let number as Double:
print("This is a double with value: \(number)")
default:
print("Unknown type")
}

Output:

This is a string

Function Call Expressions

You can use function calls in expression patterns:

swift
func isEven(_ number: Int) -> Bool {
return number % 2 == 0
}

let number = 24

switch number {
case let x where isEven(x):
print("\(x) is even")
default:
print("\(number) is odd")
}

Output:

24 is even

Custom Pattern Matching with ~=

One of the most powerful features of expression patterns is the ability to customize the ~= operator for your own types:

swift
struct Temperature {
let celsius: Double

init(celsius: Double) {
self.celsius = celsius
}

var fahrenheit: Double {
return celsius * 9/5 + 32
}
}

// Define a custom pattern matching operator
func ~= (pattern: Range<Double>, value: Temperature) -> Bool {
return pattern.contains(value.celsius)
}

let currentTemperature = Temperature(celsius: 23)

switch currentTemperature {
case -10..<0:
print("Below freezing")
case 0..<15:
print("Cool weather")
case 15..<25:
print("Pleasant weather")
case 25..<35:
print("Hot weather")
default:
print("Extreme temperature")
}

Output:

Pleasant weather

Using Expression Patterns in if-case Statements

Expression patterns aren't limited to switch statements. You can also use them in if case and guard case statements:

swift
let optionalNumber: Int? = 42

// Using if-case with expression pattern
if case 30...50 = optionalNumber ?? 0 {
print("Number is between 30 and 50")
}

// Using guard-case with expression pattern
func processNumber(_ number: Int?) {
guard case 1...100 = number ?? -1 else {
print("Number is out of valid range")
return
}
print("Processing valid number: \(number!)")
}

processNumber(42)
processNumber(101)

Output:

Number is between 30 and 50
Processing valid number: 42
Number is out of valid range

Real-world Application: Weather App

Here's a practical example showing how expression patterns could be used in a weather application:

swift
struct WeatherData {
let temperature: Double // in Celsius
let windSpeed: Double // in km/h
let precipitation: Double // in mm
let uvIndex: Int // 0-11 scale
}

func getWeatherWarning(for weather: WeatherData) -> String {
switch weather {
case let w where w.temperature > 35:
return "🔥 Extreme heat warning! Stay hydrated and avoid direct sun."
case let w where w.temperature < -10:
return "❄️ Extreme cold warning! Dress warmly and limit outdoor exposure."
case let w where w.windSpeed > 60:
return "💨 High wind warning! Secure loose items outdoors."
case let w where w.precipitation > 25:
return "🌧️ Heavy rain warning! Be aware of potential flooding."
case let w where w.uvIndex > 8:
return "☀️ High UV warning! Use sunscreen and wear protective clothing."
default:
return "No severe weather warnings."
}
}

let todaysWeather = WeatherData(temperature: 37, windSpeed: 15, precipitation: 0, uvIndex: 9)
print(getWeatherWarning(for: todaysWeather))

Output:

🔥 Extreme heat warning! Stay hydrated and avoid direct sun.

Summary

Expression patterns are a flexible and powerful feature in Swift's pattern matching system. They allow you to:

  • Match against ranges, types, and computed values
  • Customize pattern matching behavior with the ~= operator
  • Use pattern matching in switch, if case, and guard case statements
  • Create more readable and expressive code for complex conditions

By mastering expression patterns, you can write more concise, readable, and maintainable code that clearly expresses your intent.

Exercises

  1. Write a function that uses pattern matching to categorize students by their grades (A: 90-100, B: 80-89, C: 70-79, D: 60-69, F: below 60).

  2. Create a custom ~= operator for a User struct that allows matching users by age ranges.

  3. Implement a simple calculator that uses pattern matching to interpret basic arithmetic expressions.

  4. Extend the weather example to include multiple warnings in a single message when multiple conditions are met.

Additional Resources

Happy coding with Swift expression patterns!



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)