1. Learn Swift by running Scripts

Learn using command line Scripts without using Xcode UI

Santosh Rajan
Swift Programming
11 min readJun 12, 2014

--

May be it is only me, or you are like me. I like to learn a language by writing little Scripts in that language. You can write and execute Swift Scripts using the immediate mode of the Swift language compiler.

First download and install Xcode 7.

The Swift interpreter is called, not surprisingly swift. First something about the REPL before I show you how to run scripts. Running the Swift interpreter without any command line arguments will run the REPL. Now run the Swift REPL by typing swift into the terminal. And then type and run the print function as below.

$ swift
Welcome to Swift! Type :help for assistance.
1> print(“Hello World”)
Hello World
2>

You can play with the REPL to learn Swift basics. Hit Ctrl-D to exit the REPL.

Note: You can also run the examples below from the Xcode Playground.

Hello World! in Swift

However this tutorial is about running scripts. Open your code editor and create a file called hello.swift. And type the following into it.

print("Hello World!")

Now run your first program

$ swift hello.swift
Hello World!

If all goes well, you will see “Hello World” printed to your console.

You can also use the shebang to run your script as a program directly. Edit your hello.swift file to the code below.

#!/usr/bin/env swiftprint("hello world!!)

Now run the program. Change file permissions first.

$ chmod +x hello.swift
$ ./hello.swift
Hello World

Edit hello.swift to the following code and run it.

dump(Process.arguments)

dump is a function from the swift standard library. It just dumps a collection passed to it to standard output.

Process is a structure in the Swift Standard Library, and arguments is one of the public variables in that structure.

Process.arguments gives you access to an array of the command line arguments. And we just dumped that array. The output says that it has one element, and the the first element [0] is the string “hello.swift”. Now try this

$ swift hello.swift foo bar “hello world”
▿ 4 elements
  —  [0]: hello.swift
  —  [1]: foo
  —  [2]: bar
  —  [3]: hello world

The Swift Compiler

Note: On OSX Yosemite and Xcode 6.1 and above you can run the Swift Compiler by just typing swiftc in the command line.

The Swift Compiler is what compiles your Swift code to binary, and it’s called swiftc.

Now compile and run hello.swift.

$ swiftc hello.swift -o hello
$ ./hello
Hello World

print is a builtin Swift Standard Library function that prints to standard output. So we used swiftc to compile hello.swift to a binary called hello and ran the binary.

Get on with it!

Now that you know how to run a Swift program as a script, let us get on with it. Type the following program and run it.

For those not familiar with the terminal app, you can copy and paste single lines of commands into the terminal window. To edit and re-run a command just hit the up arrow. This knowledge will make running programs from the terminal a breeze.

Our first function in Swift

func doNothing() {
}
doNothing()

We defined a function with name doNothing and called that function in the next line. Your program runs without errors and does nothing, not surprisingly.

Functions return a value

Now let us see what doNothing returns if at all anything. For that we will assign the value returned by doNothing() to a new variable called nothing. You use the var statement to define variables in Swift.

func doNothing() {
}
var nothing = doNothing()

Oops we get an error! We defined a variable called nothing and assigned the return value of doNothing to it. Here is the first line of the error.

functions.swift:3:5: warning: variable ‘nothing’ inferred to have type ‘()’, which may be unexpected

So doNothing does return something. In fact every function returns something even if you don’t explicitly return anything. The error says the returned value is of type ‘()’. ‘()’ is an empty tuple. If you don’t know what that is, just assume it is a kind of an empty array for now.

func doNothing() {
}
var something: () = doNothing()

This time no errors. We set the type of variable something to the empty tuple. Try this.

func doNothing() {
}
var something: Void = doNothing()

Here we changed the type to Void and no error. You can use the type Void instead.

Now try a function that returns a String. Also, we set the variable type for something to String.

func doSomething() {
return "Hello World"
}
var something: String = doSomething()

Error!

functions.swift:4:25: error: ‘()’ is not convertible to ‘String’
var something: String = doSomething()
^
functions.swift:2:12: error: cannot convert the expression’s type ‘String’ to type ‘()’
return “Hello World”
^~~~~~~~~~~~~

Function return Types

The compiler is expecting the function to return a ‘()’ aka Void! And we are returning type String. If you return anything other than a Void from a function you need to specify its return type. So let us specify a return type for the function.

func doSomething() -> String {
return "Hello World"
}
var something: String = doSomething()

It works, now that we specified a return type. You specify a return type for a function by adding type specifier ‘-> String’ after the arguments part of the function declaration. Next try this.

Type inference in Swift

func doSomething() -> String {
return "Hello World"
}
var something = doSomething()

If you noticed, in the last line, we removed the type specifier “: String”, for the var statement. Yet it worked. That is because, the Swift compiler can infer types in variable definitions, if you provide an initial value. In the case above, the compiler looks at the Type returned by doSomething(), and infers that the variable something must be a String.

Function parameter Types

Now we will write a function, given a name, will return a greeting.

func greet(name) -> String {
return "Hello "+ name
}
var greeting: String = greet(“John”)

Error again!

functions.swift:1:12: error: use of undeclared type ‘name’
func greet(name) -> String {
^~~~

So we have to declare the argument types also, if we have arguments to pass to the function.

func greet(name: String) -> String {
return "Hello "+ name
}
var greeting = greet("John")
print(greeting)

Variable Type in Swift

Swift is a Strongly Typed Language. Which means every variable you define must have a corresponding Type, either explicitly defined or inferred. You cannot assign a value of a different type to a variable already defined. The two ways you can define a variable are by using the var or let statements.

var name = "John"
let anothername = "Bob"

The difference between the two statements is that let creates a constant. You cannot modify the value of anothername again.

var name = "John"
name = "Jill" // Ok
let anothername = "Bob"
anothername = "Ben" // error

Variable types in Swift are specified as follows

  1. In variable definitions using var and let. In this case if you initialize the variable in the same statement, the type need not be specified, the type will be inferred.
  2. In function definitions, in functions parameter list.
  3. The return Type in a function definition.

The common basic Types you will come across while using Swift are String, Int, Float, Double, Array, Dictionary. There are other Types like optionals, AnyObject. And user defined Types when you create classes, structures and enums, protocols etc which we will discuss later.

Function Type

In Swift, functions have a Type too! What is the Type of the greet function we wrote above?

(String) -> String

The above function Type indicates, that the function takes one parameter of Type String and returns a value of Type String. Separate more than one parameter Types with a comma.

Factorial Function in Swift

Here is the definition of factorial from wikipedia.

In mathematics, the factorial of a non-negative integer n, denoted by n!, is the product of all positive integers less than or equal to n. For example,

5! = 5 * 4 * 3 * 2 * 1 = 120

The value of 0! is 1, according to the convention for an empty product.

And here is the factorial function in Swift

func factorial(n: Int) -> Int {
if n == 0 {
return 1
}
var fact = 1
for i in 1…n {
fact = fact * i
}
return fact
}
print(factorial(5)) // prints 120

The Type of the factorial function is

(Int) -> Int

Given an Integer parameter n, it returns the Integer factorial of n (n!).

Within the function we first need to get rid of the edge case scenario, where n = 0. For that we use an if statement and return immediately with value 1, if the condition is true.

 if n == 0 {
return 1
}

Note that in Swift, the parenthesis around the conditional (n == 0) are not necessary.

Next we define a variable fact and initialise it with value 1. Note that we don’t specify its Type. The Swift compiler will infer the Type with the initial value given. (Int in this case).

 var fact = 1

Next we run through a for loop, from 1…n (note the triple dots).

 for i in 1...n {
fact = fact * i
}

This is one way of looping in Swift. You will see many more ways in the documentation. If you don’t want the final loop value of n to be counted (e.g. you are looping through an array from 0 to length-1) you can use ..< notation as below

for i in 0..<length

The isPrime Function in Swift

The isPrime function takes a given integer and returns true or false, based on whether the given number is a prime number or not.

Quoting from wikipedia on prime numbers.

A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.

The property of being prime (or not) is called primality. A simple but slow method of verifying the primality of a given number n is known as trial division. It consists of testing whether n is a multiple of any integer between 2 and square root of n.

The isPrime function below tests whether the give integer, is a multiple of any integer between 2 and the square root of the given integer n.

import Foundationfunc isPrime(n: Int) -> Bool {
if n < 2 {
return false // are not primes
}
var limit = Int(sqrt(Float(n)))
if limit < 2 {
return true // 2, 3 are primes
}
for i in 2…limit {
if n % i == 0 {
return false
}
}
return true
}

Notice the first line

import Foundation

Xcode provides a set of libraries you can use to get various stuff done. Foundation is one of them. We use it here because the square root function sqrt is available in this library.

The Type of the isPrime function is

(Int) -> Bool

Takes a single integer parameter and returns a boolean.

First we eliminate the possibility of the given number being less than 2 by returning false, since they are not prime numbers.

 if n < 2 {
return false // are not primes
}

Next we need to calculate the limit for the for loop, which is the square root of the given number n.

var limit = Int(sqrt(Float(n)))

The problem is that the sqrt function takes a number of Type Float and returns a value of Type Float. So first we convert the given integer n to a Float.

Float(n)

And we pass the converted value to the sqrt function

sqrt(Float(n))

And then we convert the returned Float, back to an Integer.

Int(sqrt(Float(n)))

The square root of 2 and 3 are less than 2. And our for loop starts from 2. So we eliminate those cases, by returning true, because we know 2 and 3 are primes.

 if limit < 2 {
return true // 2, 3 are primes
}

Next we run through the for loop from 2 to limit. For each integer i we calculates n modulus i, and if it is 0, n is divisible by i, and we return false. If we complete the loop without returning false, then n is a prime and we return true.

 for i in 2…limit {
if n % i == 0 {
return false
}
}
return true

All Prime numbers less than 100

The next program will print out all the prime numbers from 2 to 100 and uses the isPrime function.

var primes: [Int] = []
for i in 2…100 {
if isPrime(i) {
primes.append(i)
}
}
print(primes)
// Prints [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

First we define a variable called primes of Type Array to store the found prime numbers as we find them.

var primes: [Int] = []

Notice how you define the Type of an Array variable [Int], and how you initialise it to an empty Array [].

Next we iterate through a for loop from 2 to 100. For each value i in the loop we call

isPrime(i)

which returns true if i is a prime and false otherwise. If the returned value is true we append that value to the primes Array.

 if isPrime(i) {
primes.append(i)
}

Optionals in Swift

Try this

var num: Int = 10
print(num)

No problem! Now try this.

var num: Int
print(num)

Error!

error: variable ‘num’ used before being initialized
print(num)
^

What did we learn here? You can create a variable in Swift without initializing it. But you can’t use it until you have set a value to it.

So what is the value when a variable is not initialised? Answer is nil.

Since we are talking of integers, isn’t nil and zero the same? Yes, if you are doing Math. No, if you are doing computer science. So what is the difference.

var num: Int                 // Value is nil
var num: Int = 0 // Value is zero

In the first case, no memory is allocated for num, indicating absence of a value. In the second case, memory is allocated (4 bytes for Int type), and initialised to zero. And here is the problem

var num: Int = nil           // Error!

So the Type Int represents a range of integers from negative to positive integers including zero, but not nil.

So what do we do if we want nil to also be one of the acceptable range of values? We `lift` the Type to an Optional Type, represented by adding a ? to the basic Type.

var num: Int?
print(num) // prints nil

Another example

var num: Int?
if num == nil {
print("num is nil") // prints "num is nil"
}

All Types in Swift can be lifted to the corresponding Optional Type like Int?, Float?, String?, Array?, Dictionary? etc.

Let us try out some optional types.

var num: Int? = 10
func square(x: Int) -> Int {
return x * x
}
square(num)

Error!

error: value of optional type ‘Int?’ not unwrapped; did you mean to use ‘!’ or ‘?’?
square(num)
^

num is of optional Type Int? and the function square takes an Int. We need to unwrap the optional type while calling square. You can unwrap an optional variable by post fixing it with ‘!’. The ‘?’ is also used for unwrapping optionals in what is known as optional chaining, which we will see later.

var num: Int? = 10
func square(x: Int) -> Int {
return x * x
}
print(square(num!)) // 100

We unwrapped num by passing num! to the function. What happens if the value of the optional is nil when you unwrap? Try it!

var num: Int? = nil
func square(x: Int) -> Int {
return x * x
}
print(square(num!)) // Fatal Error!

You will get a fatal error! Never unwrap an optional if you are not sure it has a value. We can get around this using an if condition.

var num: Int? = nil
func square(x: Int) -> Int {
return x * x
}
if num != nil {
print(square(num!))
} else {
print("num is nil") // prints "num is nil"
}

Another way to solve this problem is given below

var num: Int? = 10
func square(x: Int) -> Int {
return x * x
}
if let newnum = num {
print(square(newnum)) // prints 100
} else {
print(“num is nil”)
}

Notice the line

if let newnum = num

This is known as optional binding. We create a new variable called newnum to which we assign num. However the assignment happens only if num is not nil. The else part is called if num is nil. Notice also that newnum, which is available within the if block, is an Int and not an optional. No need to unwrap it.

Next Post. Functional Programming in Swift. 2. Functional Swift

--

--

Santosh Rajan
Swift Programming

Founder www.geekskool.com. Programmer for over 30 years. Making better programmers is my passion. Bangalore. India. www.santoshrajan.com