Swift: قيم إرجاع Swift وأنواع الدوال

Functions can return more than basic types — they can return multiple values, and even return other functions. This lesson explores the full spectrum of Swift function return values and the core concept of functions as first-class citizens.

1. What You'll Learn


2. An E-commerce Developer's Real Story

(1) Pain: Writing a new function for every discount tier

Charlie is building a promotions engine. Different user tiers get different discounts:

SWIFT
func vipDiscount(_ price: Double) -> Double {
    return price * 0.8
}
func memberDiscount(_ price: Double) -> Double {
    return price * 0.9
}
func normalDiscount(_ price: Double) -> Double {
    return price
}

Every time a new discount type is added, he writes another function. When the promotion rules change, a pile of code needs updating. Strategy switching relies on hand-written if-else; there's no way to configure it dynamically.

(2) The Functions-as-Types Solution

In Swift, functions are "first-class citizens" — you can pass and store them just like Int or String:

SWIFT
// Define a discount strategy type
typealias DiscountStrategy = (Double) -> Double
// Use a function dictionary instead of if-else
let strategies: [String: DiscountStrategy] = [
    "vip": { $0 * 0.8 },
    "member": { $0 * 0.9 },
    "normal": { $0 }
]
// Switch strategy in one line
func applyDiscount(_ price: Double, level: String) -> Double {
    return strategies[level]?(price) ?? price
}

(3) Result: Configurable strategies, extensible code

Dimension Before After
Add a discount Write function + modify if-else Add a dictionary entry
Strategy switching Hard-coded if-else Dynamic key-based selection
Reusability Each strategy standalone, not composable Functions composable and passable
Test coverage One test per strategy Unified testing framework

3. Multiple Return Values and Function Overloading

(1) Returning Multiple Values with Tuples

Swift tuples let a function return several values at once:

100%
graph LR
    A[Function returns tuple] --> B[Element 1]
    A --> C[Element 2]
    A --> D[Element 3]
    B --> E["Named access: result.name"]
    C --> F["Named access: result.age"]
    D --> G["Indexed access: result.0"]
Approach Syntax When to Use
Anonymous tuple -> (Int, String) Simple grouping, names not important
Named tuple -> (sum: Int, avg: Double) Semantic field access needed
Optional tuple -> (Int, String)? Function may fail and return nil

▶ Example: Array Statistical Analysis

SWIFT
// ============================================
// Return multiple statistics using a named tuple
// ============================================
func analyze(_ numbers: [Int]) -> (count: Int, sum: Int, average: Double) {
    let count = numbers.count
    let sum = numbers.reduce(0, +)
    let average = count > 0 ? Double(sum) / Double(count) : 0
    return (count, sum, average)
}
let result = analyze([85, 90, 78, 92, 88])
print("Count: \(result.count)")
print("Sum: \(result.sum)")
print("Average: \(result.average)")

Output:

TEXT 📖 للعرض فقط
Count: 5
Sum: 433
Average: 86.6

(2) Function Overloading

Swift supports multiple functions with the same name as long as the parameter types or counts differ:

SWIFT
func area(width: Double, height: Double) -> Double {
    return width * height
}
func area(radius: Double) -> Double {
    return Double.pi * radius * radius
}
print("Rectangle area: \(area(width: 10, height: 5))")
print("Circle area: \(area(radius: 3))")

Output:

TEXT 📖 للعرض فقط
Rectangle area: 50.0
Circle area: 28.274333882308138

4. Functions as Types

(1) Function Type Syntax

Every function has a specific type, determined by its parameter types and return type:

Function Signature Function Type
func add(a: Int, b: Int) -> Int (Int, Int) -> Int
func log() -> Void () -> Void or () -> ()
func greet(_ name: String) (String) -> Void
func double(_ n: Int) -> Int (Int) -> Int
💡 Note: A function type includes only the parameter types and return type — it does not include argument labels.

▶ Example: Functions as Variables and Parameters

SWIFT
// ============================================
// Functions passed as variables and parameters
// ============================================
// 1. Define two simple functions
func add(_ a: Int, _ b: Int) -> Int { return a + b }
func multiply(_ a: Int, _ b: Int) -> Int { return a * b }
// 2. Function type variable
var operation: (Int, Int) -> Int = add
print("add: \(operation(3, 4))")
// 3. Swap the function
operation = multiply
print("multiply: \(operation(3, 4))")
// 4. Function as a parameter
func execute(_ a: Int, _ b: Int, using op: (Int, Int) -> Int) -> Int {
    return op(a, b)
}
print("execute add: \(execute(5, 6, using: add))")
print("execute multiply: \(execute(5, 6, using: multiply))")

Output:

TEXT 📖 للعرض فقط
add: 7
multiply: 12
execute add: 11
execute multiply: 30

(2) typealias for Function Type Naming

When a function type is complex or used in many places, give it a name with typealias:

SWIFT
// Define a function type alias
typealias IntOperation = (Int, Int) -> Int
// Use the alias for variables and parameters
func calculate(_ a: Int, _ b: Int, using op: IntOperation) -> Int {
    return op(a, b)
}
let op: IntOperation = { $0 * $0 + $1 * $1 }
print("Result: \(calculate(3, 4, using: op))")

Output:

TEXT 📖 للعرض فقط
Result: 25

5. Nested Functions and Functions Returning Functions

(1) Nested Functions

You can define functions inside other functions. Inner functions are only accessible within the outer function's scope:

SWIFT
// ============================================
// Nested functions: define helper functions inside
// ============================================
func formatFullName(first: String, last: String) -> String {
    // Nested helper
    func capitalize(_ text: String) -> String {
        return text.prefix(1).uppercased() + text.dropFirst().lowercased()
    }
    return "\(capitalize(first)) \(capitalize(last.uppercased()))"
}
print(formatFullName(first: "alice", last: "JOHNSON"))

Output:

TEXT 📖 للعرض فقط
Alice Johnson

(2) Functions Returning Functions

Another form of higher-order functions — returning a function:

SWIFT
// ============================================
// Function factory: generate different strategy functions by parameter
// ============================================
func makeMultiplier(factor: Double) -> (Double) -> Double {
    func multiplier(_ value: Double) -> Double {
        return value * factor
    }
    return multiplier
}
let double = makeMultiplier(factor: 2)
let triple = makeMultiplier(factor: 3)
print("double(5) = \(double(5))")
print("triple(5) = \(triple(5))")

Output:

TEXT 📖 للعرض فقط
double(5) = 10.0
triple(5) = 15.0

▶ Example: Discount Strategy Factory

SWIFT
// ============================================
// Discount factory with nested functions and function return values
// ============================================
typealias DiscountRule = (Double) -> Double
func discountFor(level: String) -> DiscountRule? {
    // Nested discount functions
    func vip(_ price: Double) -> Double { return price * 0.8 }
    func member(_ price: Double) -> Double { return price * 0.9 }
    func normal(_ price: Double) -> Double { return price }
    switch level {
    case "vip": return vip
    case "member": return member
    case "normal": return normal
    default: return nil
    }
}
if let rule = discountFor(level: "vip") {
    print("VIP discount price: $\(rule(100))")
}

Output:

TEXT 📖 للعرض فقط
VIP discount price: $80.0

6. Full Example: Promotions Engine

SWIFT
// ============================================
// Full example: Promotions engine
// Combines: multiple returns + function types + typealias + nested functions
// ============================================
import Foundation
// 1. Define function type aliases
typealias Discount = (Double) -> Double
typealias DiscountResult = (original: Double, final: Double, saved: Double)
// 2. Discount factory — returns a nested function
func createDiscount(minSpend: Double, rate: Double) -> Discount {
    func discount(_ price: Double) -> Double {
        return price >= minSpend ? price * (1 - rate) : price
    }
    return discount
}
// 3. Multiple return values — return discount result details
func applyDiscount(price: Double, rule: Discount) -> DiscountResult {
    let final = rule(price)
    let saved = price - final
    return (price, final, saved)
}
// 4. Function as parameter — batch process orders
func processOrders(_ prices: [Double], using rule: Discount) -> [DiscountResult] {
    return prices.map { applyDiscount(price: $0, rule: rule) }
}
// 5. Use the promotions engine
let memberRule = createDiscount(minSpend: 50, rate: 0.15)
let orderResults = processOrders([120, 45, 200], using: memberRule)
for result in orderResults {
    print("$\(result.original) → $\(result.final) (saved $\(result.saved))")
}

Output:

TEXT 📖 للعرض فقط
$120.0 → $102.0 (saved $18.0)
$45.0 → $45.0 (saved $0.0)
$200.0 → $170.0 (saved $30.0)

❓ FAQ

س Why do function types ignore argument labels?
ج Function types focus on type matching — the types of parameters and the return value. Labels are part of the external calling convention and do not affect type compatibility. So (a: Int) -> Void and (b: Int) -> Void are the same type.
س What's the difference between nested functions and closures?
ج Nested functions are named inner functions. Closures are typically anonymous code blocks. Nested functions can capture outer variables and behave similarly to closures, but have a name and can be called repeatedly.
س Can typealias be used with complex generic function types?
ج Yes. For example, typealias Transformer<T> = (T) -> T defines a generic function type alias. However, in Swift, typealias cannot directly express generic constraints — other mechanisms are needed for that.
س Is it better to return a tuple or a custom struct?
ج Use tuples for simple combinations (e.g. returning two Ints). Use structs for semantically complex scenarios (named fields with documentation). Tuples suit ad-hoc groupings; structs suit public APIs.
س Does function overloading hurt runtime performance?
ج No. Overload resolution happens at compile time (static dispatch), with no runtime overhead. The Swift compiler selects the correct version based on parameter types and count during compilation.

📖 Summary


📝 Exercises

  1. Beginner: Write a divide(_:_:) function that returns both quotient and remainder via a tuple. Call and print the result of divide(17, 5).
  2. Intermediate: Write a transform function for [Int] arrays that takes an (Int) -> Int type parameter and returns a new array. Then define a typealias for that function type.
  3. Challenge: Implement an "operation chain" — write a chain(_:_:) function that takes an initial Int value and an array of [(Int) -> Int] functions, applies each function to the value in sequence, and returns the final result. Create three transformation functions and compose a chain.
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%