Exploring Swift

In this article by Dr. Alex Blewitt, author of the book Swift Essentials – Second Edition, the author talks introduces us to different Swift literals.

Apple announced Swift at WWDC 2014 as a new programming language that combines experience with the Objective-C platform and advances in dynamic and statically typed languages over the last few decades. Before Swift, most code written for iOS and OS X applications was in Objective-C, a set of object-oriented extensions to the C programming language. Swift aims to build upon patterns and frameworks of Objective-C but with a more modern runtime and automatic memory management. In December 2015, Apple open-sourced Swift at https://swift.org and made binaries available for Linux as well as OS X.

(For more resources related to this topic, see here.)

Open source Swift

Apple released Swift as an open-source project in December 2015, hosted at https://github.com/apple/swift/ and related repositories. Information about the open-source version of Swift is available from the https://swift.org site. The open-source version of Swift is similar from a run-time perspective on both Linux and OS X; however, the set of libraries available differ between the two platforms.

For example, the Objective-C runtime was not present in the initial release of Swift for Linux; and as a result, several methods that are delegated to Objective-C implementations are not available. "hello".hasPrefix("he") compiles and runs successfully on OS X and iOS but is a compile error in the first Swift release for Linux.

In addition to missing functions, there are also a different set of modules (frameworks) between the two platforms. The base functionality on OS X and iOS is provided by the Darwin module, but on Linux the base functionality is provided by the Glibc module. The Foundation module, which provides many of the data types outside of the base collections library, is implemented in Objective-C on OS X and iOS, but on Linux is a clean-room re-implementation in Swift. As Swift on Linux evolves more of this functionality will be filled in but it is worth testing on both OS X and Linux specifically if cross platform functionality is required.

Finally although the Swift language and core libraries have been open-sourced, this does not apply to the iOS libraries or other functionality in Xcode. As a result it is not possible to compile iOS or OS X applications from Linux, and building iOS applications and editing user interfaces is something that must be done in Xcode on OS X.

Getting started with Swift

Swift provides a runtime interpreter that executes statements and expressions. Swift is open-source, and precompiled binaries can be downloaded from https://swift.org/download/ for both OS X and Linux platforms. Ports are in progress to other platforms and operating systems but are not supported by the Swift development team.

The Swift interpreter is called swift and on OS X can be launched using the xcrun command in a Terminal.app shell:

$ xcrun swift

Welcome to Swift version 2.2!  Type :help for assistance.

> 

The xcrun command allows a toolchain command to be executed; in this case, it finds /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift. The swift command sits alongside other compilation tools such as clang and ld, and permits multiple versions of the commands and libraries on the same machine without conflicting.

On Linux, the swift binary can be executed provided that it and the dependent libraries are in a suitable location.

The Swift prompt displays > for new statements and . for continuation. Statements and expressions typed into the interpreter are evaluated and displayed. Anonymous values are given references so they can be used subsequently:

> "Hello World"

$R0: String = "Hello World"

> 3 + 4

$R1: Int = 7

> $R0

$R2: String = "Hello World"

> $R1

$R3: Int = 7

Numeric Literals

Numeric types in Swift can represent both signed and unsigned integral values with sizes of 8, 16, 32, or 64 bits, as well as signed 32 or 64 bit floating point values. Numbers can include underscores to provide better readability; so 68_040 is the same as 68040.

> 3.141

$R0: Double = 3.141

> 299_792_458

$R1: Int = 299792458

> -1

$R2: Int = -1

> 1_800_123456

$R3: Int = 1800123456

Numbers can also be written in binary, octal, or hexadecimal using prefixes 0b, 0o (zero and the letter "o") or 0x. Note that Swift does not inherit C's use of a leading zero (0) to represent an octal value, unlike Java and JavaScript which do. Examples include:

> 0b1010011

$R0: Int = 83

> 0o123

$R1: Int = 83

> 0123

$R2: Int = 123

> 0x7b

$R3: Int = 123

Floating point literals

There are three floating point types available in Swift, which use the IEEE754 floating point standard. The Double type represents 64 bits worth of data whilst Float stores 32 bits of data. In addition, Float80 is a specialized type that stores 80 bits worth of data. (Float32 and Float64 are available as aliases for Float and Double respectively, although they are not commonly used in Swift programs.)

Some CPUs internally use 80 bit precision to perform math operations, and the Float80 type allows this accuracy to be used in Swift. Not all architectures support Float80 natively, so this should be used sparingly.

By default, floating point values in Swift use the Double type. As floating point representation cannot represent some numbers exactly, some values will be displayed with a rounding error; for example:

> 3.141

$R0: Double = 3.141

> Float(3.141)

$R1: Float = 3.1400003

Floating point values can be specified in decimal or hexadecimal. Decimal floating point uses e as the exponent for base 10, whereas hexadecimal floating point uses p as the exponent for base 2. A value of AeB has the value A*10^B and a value of 0xApB has the value A*2^B:

> 299.792458e6

$R0: Double = 299792458

> 299.792_458_e6

$R1: Double = 299792458

> 0x1p8

$R2: Double = 256

> 0x1p10

$R3: Double = 1024

> 0x4p10

$R4: Double = 4096

> 1e-1

$R5: Double = 0.10000000000000001

> 1e-2

$R6: Double = 0.01
> 0x1p-1

$R7: Double = 0.5

> 0x1p-2

$R8: Double = 0.25

> 0xAp-1

$R9: Double = 5

String literals

Strings can contain escaped characters, unicode characters, and interpolated expressions. Escaped characters start with a slash (\) and can be one of:

  • \\ Literal slash \
  • \0 The null character
  • \' Literal single quote '
  • \" Literal double quote "
  • \t Tab
  • \n Line feed
  • \r Carriage return
  • \u{NNN} Unicode character such as the Euro symbol \u{20AC} or smiley \u{1F600}

An interpolated string has an embedded expression which is evaluated, converted into a String, and inserted into the result:

> "3+4 is \(3+4)"

$R0: String = "3+4 is 7"

> 3+4

$R1: Int = 7

> "7 x 2 is \($R1 * 2)"

$R2: String = "7 x 2 is 14"

Variables and constants

Swift distinguishes between variables (which can be modified) and constants (which cannot be changed after assignment). Identifiers start with an underscore or alphabetic character, followed by an underscore or alphanumeric character. In addition, other Unicode character points (such as emoji) can be used, although box lines and arrows are not allowed; consult the Swift language guide for the full set of allowable Unicode characters. Generally, Unicode private use areas are not allowed, and identifiers cannot start with a combining character (such as an accent).

Variables are defined with the var keyword and constants are defined with the let keyword. If the type is not specified, it is automatically inferred:

> let pi = 3.141

pi: Double = 3.141

> pi = 3

error: cannot assign to value: 'pi' is a 'let' constant

note: change 'let' to 'var' to make it mutable

> var i = 0

i: Int = 0

> ++i

$R0: Int = 1

Types can be explicitly specified. For example, to store a 32 bit floating point value, the variable can be explicitly defined as a Float:

> let e:Float = 2.718

e: Float = 2.71799994

Similarly, to store a value as an unsigned 8 bit integer, explicitly declare the type as UInt8:

> let ff:UInt8 = 255

ff: UInt8 = 255

A number can be converted to a different type using the type initializer, or a literal assigned to a variable of a different type, provided that it does not underflow or overflow:

> let ooff = UInt16(ff)

ooff: UInt16 = 255

> Int8(255)

error: integer overflows when converted from 'Int' to 'Int8'

Int8(255)

^

> UInt8(Int8(-1))

error: negative integer cannot be converted to unsigned type 'UInt8'

UInt8(Int8(-1))

^

Summary

The Swift interpreter is a great way of learning how to program in Swift. It allows expressions, statements, and functions to be created and tested along with a command line history that provides editing support. The basic collection types of arrays and collections, the standard data types such as strings and numbers, optional values and structures were presented. Control flow and functions with positional, named, and variadic arguments, along with default values were also presented. Finally, the ability to write Swift scripts and run them from the command line was also demonstrated.

Resources for Article:


Further resources on this subject:


You've been reading an excerpt of:

Swift Essentials - Second Edition

Explore Title