Hashbang Swift: Part I

I’ve been playing a lot with Swift since Apple introduced it about a month ago. Most of the time I use it on Xcode, working on apps, but frequently I find myself using Playgrounds, either to test an extension or to practice the language.

Today I decided to try something different, to run Swift code right from the terminal, using the swift command. This new command is installed by Xcode 6, but it’s not visible while Xcode 5 is the default Xcode set for development. To make it visible, it’s necessary to switch to Xcode 6 by running the command xcrun 1

1
$ xcrun -s /Application/Xcode6-Beta2.app

No only does xcrun work for setting the default Xcode but also for finding and running bundled command line tools and showing SDKs paths for iOS and Mac OS X development. To find the swift command, one needs to run xcrun -f swift and, to run it, xcrun swift. To show the SDK path, xcrun --show-sdk-path --sdk macosx for OSX and xcrun --show-sdk-path --sdk iphoneos for iOS.

Back to Swift, the swift comand invokes Swift’s REPL, similarly to what irb does for Ruby and python does for Python. One can use it to try Swift from the terminal

1
2
3
4
5
6
7
8
9
10
11
12
$ swift
Welcome to Swift!  Type :help for assistance.
  1> let a = [1, 2, 3, 4]
a: Int[] = size=4 {
  [0] = 1
  [1] = 2
  [2] = 3
  [3] = 4
}
  2> println("array size is \(a.count)")
array size is 4
  3>

But clearly the plain swift is not enough to make a Swift source file run from the terminal, and that’s where the immediate mode -i takes part. It takes the source file passed as parameter to the swift command and runs it.

1
2
$ xcrun swift -i hello.swift
hello, swift

That’s something, but it’s not perfect yet. The desirable solution would be running the source file as a script:

1
$ ./hello.swift

And that’s where the hashbang enters. Hasbang (or simply #!) is a Unix-like mechanism used to describe the application responsible for handling that file. It’s declared in the very first line of the file, followed by the source code that is expected to run.

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/xcrun swift -i

func hanoi<T>(numberOfDisks n :Int, fromRod f: T, toRod t: T, usingRod u: T, closure: (T, T) -> ()) {
    if n > 0 {
        hanoi(numberOfDisks: n - 1, fromRod: f, toRod: u, usingRod: t, closure)
        closure(f, t)
        hanoi(numberOfDisks: n - 1, fromRod: u, toRod: t, usingRod: f, closure)
    }
}

hanoi(numberOfDisks: 4, fromRod: "A", toRod: "B", usingRod: "C") {
    println("Move from \($0) to \($1)")
}

Once the hashbang is set, the file can have its mode bits changed to make it executable.

1
$ chmod +x hanoi.swift

And, finally, Swift running from the terminal:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ./hanoi.swift
Move from A to C
Move from A to B
Move from C to B
Move from A to C
Move from B to A
Move from B to C
Move from A to C
Move from A to B
Move from C to B
Move from C to A
Move from B to A
Move from C to B
Move from A to C
Move from A to B
Move from C to B

Easy peasy! The second half of this post covers frameworks.


  1. Xcode 6 is currently in Beta 2.

Copyright © 2014 - Otavio Cordeiro. Powered by Octopress