Swift: تعريف دوال Swift والوسائط: من المبتدئ إلى المتقدم

Functions are the fundamental building blocks of code in Swift. This lesson teaches you how to define functions and use every parameter form flexibly, making your code more semantic and reusable.

1. What You'll Learn


2. A Backend Engineer's Real Story

(1) Pain: Unclear parameter meaning at the call site

Bob is developing an e-commerce order system. He wrote a function to calculate the total order price:

SWIFT
func calculate(price: Double, count: Int, rate: Double) -> Double {
    return price * Double(count) * (1 - rate)
}
// At the call site — parameter meaning is guesswork
let result = calculate(price: 100, count: 3, rate: 0.1)

The team split over what rate: 0.1 meant — some thought it was a 10% tax, others thought it was a 10% discount. The function signature didn't express the semantic role of each parameter.

(2) The Argument Label Solution

Swift lets you define both an external label and an internal name for each parameter, making the call site read like natural language:

SWIFT
func calculate(price: Double, count: Int, discount rate: Double) -> Double {
    return price * Double(count) * (1 - rate)
}
// Call site is clear: "discount" tells you it's a discount rate
let result = calculate(price: 100, count: 3, discount: 0.1)

(3) Result: Semantically clear function calls

Dimension Before After
Parameter meaning Pure guesswork Understandable at the call site
Code readability Must jump to definition Meaning clear in one line
Team communication Frequent debates over meaning Self-documenting function signature
Maintenance efficiency Global search on parameter changes Local changes, no ambiguity

3. Basic Function Definition

A function is a reusable block of code in Swift, defined with the func keyword.

100%
graph LR
    A[func keyword] --> B[Function name]
    B --> C[Parameter list]
    C --> D[Return arrow & type]
    D --> E[Function body]
    A --> F["func greet(name: String) -> String { return \"Hello \\(name)\" }"]
Component Required Notes
func keyword Yes Marks a function declaration
Function name Yes Identifies the function, use camelCase
Parameter list () Yes Empty parentheses even with no parameters
Return -> Type No Omit to return Void
Body {} Yes The code block executed by the function

(1) No Parameters, No Return Value

SWIFT
func sayHello() {
    print("Hello!")
}
sayHello() // Call

Output:

TEXT 📖 للعرض فقط
Hello!

(2) Parameters and Return Values

SWIFT
func add(a: Int, b: Int) -> Int {
    return a + b
}
let sum = add(a: 5, b: 3)
print("5 + 3 = \(sum)")

Output:

TEXT 📖 للعرض فقط
5 + 3 = 8

▶ Example: Order Amount Calculation

SWIFT
// ============================================
// Calculate order total including tax
// ============================================
func orderAmount(price: Double, quantity: Int) -> Double {
    return price * Double(quantity)
}
let amount = orderAmount(price: 29.99, quantity: 3)
print("Order amount: $\(amount)")

Output:

TEXT 📖 للعرض فقط
Order amount: $89.97

4. Argument Labels and Default Values

(1) Argument Labels

Swift lets you specify an external label (used at the call site) and an internal name (used inside the function body) for each parameter:

Style Syntax Call Site When to Use
Label = name func foo(name: String) foo(name: ...) Parameter name is semantic enough
External label func foo(with name: String) foo(with: ...) Call reads like natural language
Omit label func foo(_ name: String) foo(...) Verb already expresses the parameter
Combinations Varying labels Flexible Custom requirements

▶ Example: Comparing Label Styles

SWIFT
// ============================================
// Three argument label styles compared
// ============================================
// 1. Default — label equals name
func greet1(name: String) {
    print("Hello, \(name)")
}
// 2. Custom external label
func greet2(to name: String) {
    print("Hello, \(name)")
}
// 3. Omit external label (underscore)
func greet3(_ name: String) {
    print("Hello, \(name)")
}
greet1(name: "Alice")
greet2(to: "Bob")
greet3("Charlie")

Output:

TEXT 📖 للعرض فقط
Hello, Alice
Hello, Bob
Hello, Charlie

(2) Default Parameter Values

When you provide a default value for a parameter, callers can omit that argument:

SWIFT
func makeCoffee(size: String, sugar: Int = 1) -> String {
    return "\(size) coffee with \(sugar) sugar(s)"
}
print(makeCoffee(size: "Large"))           // Uses default sugar
print(makeCoffee(size: "Medium", sugar: 0)) // Custom sugar

Output:

TEXT 📖 للعرض فقط
Large coffee with 1 sugar(s)
Medium coffee with 0 sugar(s)

💡 Tip: Place default parameters at the end of the parameter list to avoid ambiguity at call sites.


5. Variadic Parameters and inout

(1) Variadic Parameters

A variadic parameter accepts zero or more values of a given type and is available as an array inside the function body:

SWIFT
func sum(_ numbers: Double...) -> Double {
    var total = 0.0
    for number in numbers {
        total += number
    }
    return total
}
print(sum(1, 2, 3))       // 3 arguments
print(sum(10, 20))         // 2 arguments
print(sum())               // 0 arguments

Output:

TEXT 📖 للعرض فقط
6.0
30.0
0.0
Trait Description
Syntax Add ... after the type
Count 0 to any number
Type All values must be the same type
Position At most one per function; should be the last parameter

(2) inout Parameters

An inout parameter lets a function modify the caller's variable — essentially pass-by-reference rather than by copy:

SWIFT
// ============================================
// inout parameter: swapping two variables
// ============================================
func swapValues(_ a: inout Int, _ b: inout Int) {
    let temp = a
    a = b
    b = temp
}
var x = 10
var y = 20
swapValues(&x, &y)
print("x = \(x), y = \(y)")

Output:

TEXT 📖 للعرض فقط
x = 20, y = 10

⚠️ Note: Prefix the variable with & when passing to an inout parameter. You cannot pass constants or literals.

▶ Example: Universal Average Calculator

SWIFT
// ============================================
// Variadic + inout combined: compute average and track calls
// ============================================
func average(_ scores: Double..., record callCount: inout Int) -> Double {
    callCount += 1
    guard !scores.isEmpty else { return 0 }
    var total = 0.0
    for score in scores {
        total += score
    }
    return total / Double(scores.count)
}
var callTimes = 0
print("Average: \(average(85, 90, 78, record: &callTimes))")
print("Average: \(average(100, 95, record: &callTimes))")
print("Function called \(callTimes) times")

Output:

TEXT 📖 للعرض فقط
Average: 84.33333333333333
Average: 97.5
Function called 2 times

6. Full Example: Order Discount Calculator

SWIFT
// ============================================
// Full example: Order discount calculator
// Combines argument labels, defaults, variadic, inout
// ============================================
import Foundation
// 1. Compute subtotal (variadic)
func subtotal(_ prices: Double...) -> Double {
    var total = 0.0
    for price in prices {
        total += price
    }
    return total
}
// 2. Apply discount (default parameter + argument label)
func applyDiscount(to total: Double, rate: Double = 0.1) -> Double {
    return total * (1 - rate)
}
// 3. Log orders (inout parameter)
func logOrder(_ description: String, counter: inout Int) {
    counter += 1
    print("[\(counter)] \(description)")
}
// 4. Simulate order processing
var orderCount = 0
let item1 = subtotal(29.99, 49.99)
let item2 = subtotal(9.99, 14.99, 24.99)
logOrder("Item 1 subtotal: $\(item1)", counter: &orderCount)
logOrder("Item 2 subtotal: $\(item2)", counter: &orderCount)
let total1 = applyDiscount(to: item1, rate: 0.15)
let total2 = applyDiscount(to: item2)
let finalTotal = total1 + total2
logOrder("Final total: $\(finalTotal)", counter: &orderCount)

Output:

TEXT 📖 للعرض فقط
[1] Item 1 subtotal: $79.98
[2] Item 2 subtotal: $49.97
[3] Final total: $112.94

❓ FAQ

س What's the difference between argument label and parameter name?
ج The argument label (external name) is used at the call site. The parameter name (internal name / local name) is used inside the function body. The former serves call-site readability; the latter serves internal semantics. They can be the same or different.
س How is inout different from a global variable?
ج An inout parameter behaves like a local variable inside the function and writes back to the original only when the function returns. A global variable can be read and written directly, but reduces maintainability and testability. inout is the safer choice.
س What's the difference between variadic and array parameters?
ج Variadic parameters don't require explicitly constructing an array at the call site — you just pass comma-separated values. Array parameters require the [1, 2, 3] form. Variadic is more concise.
س Can a function have more than one variadic parameter?
ج No. Each function can have at most one variadic parameter, and it should typically come last in the parameter list. If you need multiple variable-length parameters, consider using array parameters instead.
س What does a function return when the arrow is omitted?
ج Omitting -> Type is equivalent to returning Void (the empty tuple ()). The function body can omit the return statement. For example, func log() { print("log") } returns Void.

📖 Summary


📝 Exercises

  1. Beginner: Write a greet function that accepts name (String) and greeting (String, default "Hello") and prints a greeting. Call it at least twice using two different argument label styles.
  2. Intermediate: Write a calculateBMI function that accepts weight (kg, Double) and height (m, Double), returning the BMI value. Use argument labels so the call site reads like calculateBMI(weight: 75, height: 1.8). Also add an inout parameter to track the number of calls.
  3. Challenge: Write a gradesAnalyzer function that uses variadic parameters to accept any number of scores and returns the highest, lowest, and average scores. Use an inout parameter to maintain an analysis history (append the count of each analysis to an array). Print the history at the end.
Web-Tutorial.com

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

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

100%