Swift Syntax

Swift is an open-source, multi-paradigm language released by Apple in 2014 and designed by Chris Lattner. Its syntax is concise and expressive: statements are separated by newlines (semicolons are optional), blocks are delimited by braces, and the two keywords let and var make mutability an explicit choice at every declaration.

This page establishes the skeleton every later lesson builds on: how a Swift file is organised, how statements are terminated, how to write comments, and the naming rules the compiler enforces.

Program Structure

A Swift program is a set of declarations spread across one or more source files. Declarations can sit at file scope or be nested inside types and functions. There is no mandatory namespace or class wrapper — unlike Java or C#, a bare statement at the top of a file is legal and will run.

Source Files

A file that contains top-level executable statements is the program: those statements run from top to bottom in the order written. This style is used for scripts, playgrounds, and small command-line tools.

// main.swift — top-level code runs immediately, top to bottom
let greeting = "Hello, Swift"
print(greeting)               // prints: Hello, Swift

var counter = 0
counter += 1                  // top-level statements execute in order
print(counter)                // prints: 1

In a project built from more than one file, exactly one file may contain top-level code, and by convention that file is named main.swift. Every other file may contain only declarations (types, functions, extensions).

Importing Modules

The import statement brings the public API of a module into the current file. import Foundation adds Apple's base libraries (dates, URLs, filesystem, string helpers); import SwiftUI adds the declarative UI framework.

import Foundation           // Date, URL, FileManager, ...
// import SwiftUI            // UI framework (Apple platforms)

let now = Date()             // Foundation type is visible after the import
print(now)                   // prints the current date and time

Import only what a file uses, and remember that imports are never transitive: importing a module in one file does not expose its names in another file.

Entry Point & @main

On Apple platforms a command-line tool may instead mark a type with @main and provide a static main() method. The runtime then calls that method as the entry point, which is the style used by iOS and macOS apps.

import Foundation

@main                        // this type owns the program entry point
struct App {
    static func main() {     // called once when the program starts
        print("Starting…")   // no main.swift file is needed here
    }
}

Never mix both styles in one target: if a main.swift exists, do not also use @main, or the compiler reports a duplicate entry point.

Statements & Blocks

A statement is one complete instruction. A block is a group of statements wrapped in braces { … } that also forms a scope. Control-flow bodies and function bodies are always blocks.

Newline-Separated Statements

Swift ends a statement at the end of a line, so the semicolon is optional. You need one only when two statements share a physical line — a style worth avoiding for readability.

let a = 1
let b = 2
let c = a + b               // one statement per line: no semicolons needed

let d = 4; let e = 5        // legal but crowded: two statements, one line
print(c, d, e)              // prints: 3 4 5

Because newlines are significant, an expression that continues on the next line must leave the parser expecting more input — typically by ending the line with an operator or an opening bracket.

// A trailing operator tells the compiler the statement continues below
let total = 1 +
            2 +
            3
print(total)                // prints: 6

let values = [
    1, 2, 3                 // inside brackets newlines are ignored
]
print(values.count)         // prints: 3

Scope Blocks

Braces create a nested scope. Names declared inside a block are invisible outside it, and the block's statements run only when control reaches them.

let outer = "visible everywhere"

do {                        // do { } alone is a plain scope block
    let inner = "only inside"
    print(outer, inner)     // both names are in scope here
}
// print(inner)             // ❌ error: cannot find 'inner' in scope

Wrapping temporary work in do { } keeps short-lived names from leaking into the rest of a function without forcing you to write a helper function.

Comments

Comments document intent for humans and are stripped before compilation. Swift offers line, block, and documentation comments.

Line Comments

// comments out the rest of the line. It is the form you will use most, including short notes placed after code.

// A full-line comment explaining the next step
let taxRate = 0.19          // trailing comment: 19% VAT

Block Comments

/* … */ spans multiple lines, and — unlike C — Swift block comments nest, so you can comment out a region that already contains comments.

/* This block is disabled for now
   /* an inner comment is fine — nesting is supported */
   print("never runs")
*/
print("block comments nest safely")   // prints: block comments nest safely

Documentation Markup

/// marks a documentation comment. Tooling reads these to build Quick Help in Xcode and generated API docs, and understands directives such as - Parameter: and - Returns:.

/// Returns the area of a rectangle.
/// - Parameters:
///   - width: the horizontal size, in points.
///   - height: the vertical size, in points.
/// - Returns: the area as a `Double`.
func area(width: Double, height: Double) -> Double {
    return width * height
}

Identifiers & Naming

An identifier names a value, type, function, or module. It may contain letters, digits, underscores, and many Unicode characters, but it cannot begin with a digit.

Naming Conventions

Swift style is a convention the compiler does not enforce: lowerCamelCase for values and functions, UpperCamelCase for types, and no underscores between words.

let maxRetryCount = 3       // value: lowerCamelCase
struct UserProfile { }      // type: UpperCamelCase
func sendMessage() { }      // function: lowerCamelCase

Keywords & Escapes

Reserved words such as class, for, and default cannot normally be names. When a name must match an external API, wrap it in backticks to escape it.

let `default` = "escaped keyword used as a name"
print(`default`)            // prints: escaped keyword used as a name

Common Pitfalls

Stray Semicolons

Old habits from C-family languages lead to trailing semicolons. They compile, but they add noise; two in a row even create an empty statement.

let x = 10;                 // unnecessary trailing semicolon
print(x)                    // prints: 10 — works, but off-style

Case Sensitivity

Swift is fully case-sensitive. total, Total, and TOTAL are three different names, and a wrong capital yields a "cannot find in scope" error rather than a silent bug.

let total = 5
// print(Total)             // ❌ error: cannot find 'Total' in scope — wrong case

You now know how a Swift file is organised, that newlines end statements, that blocks create scopes, and how to document what you write. Next: Variables & Constants turns these declarations into working values.