A Taste of Swift part 2

Updated vegaseat 2 Tallied Votes 507 Views Share

Part 2 of exploring/tasting the Swift language takes a look at dictionaries; process flow controls like loops, if/else and switch/case; functions and sorting.

I hope I can follow this up with part 3, a closer look at class operations.

//
//  main.swift
//  Taste_of_swift2
//
// exploring Apple's Swift language, part 2
// vegaseat   08jun2015    used Swift version 1.2

import Foundation

// dictionary ...

// empty dictionary
var staff_name_pay = [String: Float]()
println(staff_name_pay)                // [:]

// add first key:value pair (here name:pay pair)
// staff_name_pay[key] = value
staff_name_pay["Egon Senf"] = 4503.67
println(staff_name_pay)                // [Egon Senf: 4503.67]

// create a name:age dictionary and start populating it
// name is a string and age is an integer
var person_age:[String: Int] = ["Abby": 24, "Udo": 18, "Joe": 27]
for (name, age) in person_age {
    println((name, age))
}

// removes "Udo" from the dictionary
person_age["Udo"] = nil

println(person_age)   // [Joe: 27, Abby: 24]

// change the value for a given key
person_age.updateValue(22, forKey: "Abby")

println(person_age)   // [Joe: 27, Abby: 22]

// create an array of all the keys
var person_keys = Array(person_age.keys)
println(person_keys)    // [Joe, Abby]

// create an array of all the values
var person_values = Array(person_age.values)
println(person_values)  // [27, 22]

println("---------------------")

// loops ...

// by default k is a constant
// note that k is local to the loop
// 1..<4 implies 1 to less than 4
for k in 1..<4 {
    print(k)      // 123
    //print(k++)  // this would be an error since k is a constant
}

println("\n---------------------")

// 1...4 implies 1 to 4 (inclusive)
for k in 1...4 {
    print(k)      // 1234
}

println("\n---------------------")

for c in "abcd" {
    print(c); print(" ")     // a b c d
}

println("\n---------------------")


// can also use traditional C style for loop
// initialization; condition; increment
// use var k to allow k to be changed
// again k is local to the loop
for var k = 0; k < 4; k++ {
    print(String(k) + " ")    // 0 1 2 3
}

println("\n---------------------")

// there is also a while loop
var count = 1
while count < 15 {
    print(count); print(" ")   // 1 4 7 10 13
    count += 3
}

println("\n---------------------")

// the do/while loop goes through the code lines once before
// checking the conditions
var arr2:[Int] = []
var qq = 1
do {
    arr2.append(qq)
    qq *= 10
    
} while qq <= 10000

println(arr2)  // [1, 10, 100, 1000, 10000]

println("---------------------")

// switch/case ...

var range = 20

switch range {
case 0...9:
    println("ones")
case 10...19:
    println("tens")
case 20...29:
    println("twenties")
default:
    println("out of range")
}

var color = "orange red"

switch color {
case "blue":
    println("You like blue")
case "red":
    println("You like red")
case let x where x.hasSuffix("red"):
    println("You like anything with red in it")
case "green":
    println("You live green")
case "purple", "pink":
    println("Ah, the pink and purple kind")
default:
    println("not used")
}


println("---------------------")

// if/else ...

var tem = 45  // deg F

if tem < 30 {
    println("it's cold")
}
else if tem < 40 {
    println("it's cool")
}
else if tem < 70 {
    println("refreshing")
}
else {
    println("let's go to the beach")
}

println("---------------------")

// functions ...

// a function without parameters
func greeting() {
    println("Hello!")
}

// call the function
greeting()  // Hello!

// a function with one input parameter and no return parameter
// by default an empty tuple () meaning void is returned
// any input parameter names are local to the function
// by default they are constants unless prefixed with var
func greeting2(name: String) {
    println("Hello \(name)!")
}

greeting2("Heidi")  // Hello Heidi!

// a function with 2 input parameters and one return parameter
// notice the -> to indicate return type
func greeting3(first: String, last: String) -> String {
    var s = "Hello \(first) \(last)!"
    return s
}

println(greeting3("Fred", "Ferkel"))  // Hello Fred Ferkel!

// a function with 2 return parameters, a tuple () is used
// as an option the return parameters are named
func getNames() -> (first: String, last: String) {
    return ("Fred", "Ferkel")
}

// returned tuple
let tup = getNames()
// use the names from the functions return parameter via a dot syntax
var friend = "\(tup.first) \(tup.last) is my friend."

println(friend) // Fred Ferkel is my friend.

// you can also use the returned tuple index
println(tup.0)  // Fred
println(tup.1)  // Ferkel

// a function with a default parameter
func greeting4(name: String, greet: String = "Hello") {
    println(greet + " " + name + "!")
}

// use default greet
greeting4("Barnie")  // Hello Barnie!
// or supply greet
greeting4("Barnie", greet: "Good morning")  // Good morning Barnie!

// a function with a variadic parameter (count of numbers varies)
// one variadic parameter allowed, has to be last in parameter list
func meanf(numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    // cast numbers.count to Double to avoid integer division
    return total / Double(numbers.count)
}

var mean = meanf(1, 2.5, 3, 4.2, 5)
println(mean)  // 3.14

// create an array of strings
var friends: [String] = ["Frank", "William", "Tom"]

// a closure is a function within a function
// here map() contains an unnamed function {} like this ...
var friends_upper = friends.map({
    (s1: String) -> String in
    return s1.uppercaseString
})

println(friends_upper)  // [FRANK, WILLIAM, TOM]

// this can be shortened to ..
var friends_upper2 = friends.map({
    s1 in s1.uppercaseString
})

println(friends_upper2)  // [FRANK, WILLIAM, TOM]

// closures can be further simplified
// to use {} on one line you need the spaces!
var friends_upper3 = friends.map({ $0.uppercaseString })
// or simply ...
var friends_upper4 = friends.map { $0.uppercaseString }

println(friends_upper3)  // [FRANK, WILLIAM, TOM]
println(friends_upper4)  // [FRANK, WILLIAM, TOM]

// a function using "inout" parameters
// x and y cannot be constants
// x and y are are passed as addresses
func swap(inout x: Int, inout y: Int) {
    var t = x
    x = y
    y = t
    // no "return" needed
}

var x = 3
var y = 7
println("Before swap x = \(x)  y = \(y)")
// pass the addresses of x and y (pass by reference)
swap(&x, &y)
println("After swap  x = \(x)  y = \(y)")


// write a name inside angle brackets to make a generic function
// allows for different types of parameter item
func repeat<ItemType>(item: ItemType, times: Int) -> [ItemType] {
    var result = [ItemType]()
    for i in 0..<times {
        result.append(item)
    }
    return result
}
// implied type is string (by inference)
println(repeat("knock", 4)) // [knock, knock, knock, knock]
// implied type is float/double
println(repeat(12.99, 4))   // [12.99, 12.99, 12.99, 12.99]
// or specify type this way
var big: Int64 = 123456789
println(repeat(big, 3))   // [123456789, 123456789, 123456789]

println("---------------------")

// sorting ...

// helper functions for sorted()
func decending(s1: String, s2: String) -> Bool {
    return s1 > s2
}

func ascending(s1: String, s2: String) -> Bool {
    return s1 < s2
}

var names: [String] = ["Karl", "Norman", "Bill", "Larry"]

// apply helper function references to function sorted()
println(sorted(names, ascending))  // [Bill, Karl, Larry, Norman]
println(sorted(names, decending))  // [Norman, Larry, Karl, Bill]

var names2: [String] = ["Zoey", "Tom", "Abby"]

// apply simplified closure function to function sorted()
// compares two parameters $0 and $1
println(sorted(names2, { $0 < $1 }))  // [Abby, Tom, Zoey]
println(sorted(names2, { $0 > $1 }))  // [Zoey, Tom, Abby]

// apply to inplace sort() function (use > for decending sort)
names2.sort { $0 < $1 }
println(names2)          // [Abby, Tom, Zoey]

// really short syntax via an operator function
// Swift infers that the operator compares 2 values
names2.sort( > )
println(names2)          // [Zoey, Tom, Abby]
ddanbe 2,724 Professional Procrastinator Featured Poster

Nice. But it feels like:"Been there, done that..". Change some syntax and some extras, 'et voilĂ ' a new language is born.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

At first glance Swift looks like another boring curly brace language without the pesky/redundant semicolons. It does have some modern features. Swift is used by Apple developers for the development of OS X and iOS apps.

I like that long lists of often confusing imports and header files are avoided. C, C++, Objective-C and Swift are part of Apple's Xcode development tool. I use the Xcode IDE on my fancy Mac and more or less accidentally bumped into Swift. It looks like Apple plans to make Swift open source for Linux soon. It needs more work to compete with MS Studio languages, Python and Google's Go.

Note that Swift version 2 is out in beta and has made a number of positive changes to the syntax and added improved error handling.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Swift was made to replace Objective C used with Apple's Cocoa GUI toolkit for apps, including touch sensitive apps. Apple's free Xcode IDE makes building GUI applications with Cocoa fairly easy with its drag and drop approach.

Note: Objective C is quite an ugly bear.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Apple's Xcode IDE gives you access to the playground where you can test out short segments of Swift code and see the results as you type.

Similar to the Python shell or iPython Notebook.

Even if you don't have an Apple computer, you can enjoy the fun of using the Swift computer language. Just go onto the Swift online playground at swiftstub.com and start typing Swift code!

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Some experiments in the Swift playground ...

    String(255, radix: 2)              // "11111111"
    String(255, radix: 16)             // "ff"
    String(format:"hex 255 = %X", 255) // "hex 255 = FF"
    var binValue = 0b0011              // 3
    var hexValue = 0xff                // 255
    String(0xff, radix: 10)            // 255
    0b0100                             // 4
    0b0100 << 2                        // 16
    sqrt(3.14)                         // 1.772004514666935

    // cmd click on sqrt to get list of math functions
    // option click on any object name for declaration info

A note of caution:
Don't have two playgrounds running at the same time, your Apple computer is likely to freeze up!

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

One more function example tested on the Swift playground ...

// recursive function ...
// n changes so use var n
func factorial(var n: Int) -> Int {
    // use the very handy ternary expression "? :"
    // if n == 0 then 1 "exit condition"
    // else n * factorial(n - 1) "recurse with lower n"
    return n == 0 ? 1 : n * factorial(n - 1)
}

println("factorial(5) = \(factorial(5))")   // factorial(5) = 120
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague
// Python-like console user input
func input(prompt: String) -> String {
    print(prompt)
    var keyboard = NSFileHandle.fileHandleWithStandardInput()
    var dataIn = keyboard.availableData
    // convert to a String, use ! to remove option()
    var str = String(NSString(data: dataIn, encoding: NSUTF8StringEncoding)!)
    // remove trailing newline char from string
    str.removeAtIndex(str.endIndex.predecessor())
    return str
}

var name = input("Please enter your name: ")
println("Hello \(name), nice name!")
ddanbe 2,724 Professional Procrastinator Featured Poster

Swift was made to replace Objective C
Is this true? Is Apple going to drop the Objective C monster?

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

I am just learning Swift on my new Mac computer. Coming from a C/C++/Python background, Swift is manageable. If I would be forced to use Objective C, I would have dumped the whole thing. I am sure that some of the Apple engineers were experiencing nausea too, so they started developing Swift. Apple seems to stand behind that effort.

There are plans to make Swift Open Source and port it to Linux too.

ddanbe 2,724 Professional Procrastinator Featured Poster

Yes, exactly. Objective c is what has driven me to Windows and C#. Perhaps(like it was in the previous century) my next thing will again be a Mac and Swift.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague
// use enumerator to give switch/case a more readable syntax
enum Planet {
    case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

var myPlanet = Planet.Earth
// change it
myPlanet = .Venus

switch myPlanet {
case .Earth:
    println("You live on Earth")
case .Mars:
    println("You live on Mars")
case .Venus:
    println("You live on Venus")
default:
    println("You live nowhere")
}
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Apple is going in the right direction with Swift. Now they have to work improving the Cocoa GUI toolkit and the UIKit for iOS.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague
var mixed: [Any] = [12, 12.34, "Frank", (4, 7)]

// use "as" operator to allow for different types in switch/case
for mix in mixed {
    switch mix {
    case let someInt as Int:
        println("integer = \(someInt)") // integer = 12
    case let someDouble as Double:
        println("double = \(someDouble)") // double = 12.34
    case let someString as String:
        println("string = \"\(someString)\"") // string = "Frank"
    case let (x, y) as (Int, Int):
        println("(x, y) point = (\(x), \(y))") // (x, y) point = (4, 7)
    default:
        println("something else")    }
}
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague
// create a random integer in a range from low to high (inclusive)
// # forces low: and high: use in function call
func randomIntRange(#low: Int, #high: Int) -> Int {
    let range = high - (low - 1)
    return (Int(arc4random()) % range) + low
}

var arr = [Int]()
for k in 1...5 {
    var rn = randomIntRange(low: 5, high: 10)
    println(rn)
    arr.append(rn)
}
println(arr)  // eg. [10, 9, 6, 5, 9]
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague
// create an empty dictionary of [strKey:intArray]
var mydict2 = [String: [Int]]()

// load the first key
mydict2["key1"] = [1, 2, 3]
// append to array in key1
mydict2["key1"]!.append(4)
// show contents
println(mydict2)  // [key1: [1, 2, 3, 4]]
// or ...
mydict2["key1"]! += [5]
// show contents
println(mydict2)  // [key1: [1, 2, 3, 4, 5]]

mydict2["key1"]! += [6, 7]
// show contents
println(mydict2)  // [key1: [1, 2, 3, 4, 5, 6, 7]]
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague
// create an array of strings
var friends = ["Frank", "William", "Tom"]

// a closure is a function within a function
// here map() contains an unnamed function {}
// similar to lambda in Python
var friendsUpper = friends.map({
    // receives a string and returns a string
    (s1: String) -> String in
    return s1.uppercaseString
})

println(friendsUpper)  // [FRANK, WILLIAM, TOM]

// shorterhand closure version ...
var friendsUpper2 = friends.map() {$0.uppercaseString}

println(friendsUpper2)  // [FRANK, WILLIAM, TOM]
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

An interesting application of switch/case ...

// is a character upper case?
func isUpper(c: Character) -> Bool {
    switch c {
        case "A"..."Z": return true
        default: return false
    }
}

var ms = "Hello"
// get first character
var fc = Array(ms)[0]
println(isUpper(fc))  // true
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

A little math ...

// get the nth Fibonacci number in the series
func nthFiboBinet(n: Double) -> Int {
    // approximation using Binet's formula'
    // accuracy suffers above n = 70
    let Phi = 1.6180339887498948
    return Int(round(pow(Phi, n)/sqrt(5)))
}

println(nthFiboBinet(0))   // 0
println(nthFiboBinet(15))  // 610

// the 70th fibo should be    190392490709135
println(nthFiboBinet(70))  // 190392490709135  (still OK)

// the 71st fibo should be    308061521170129
println(nthFiboBinet(71))  // 308061521170130

// the 75th fibo should be    2111485077978050
println(nthFiboBinet(75))  // 2111485077978055

Phi is also called the Golden Ratio, the positive solution of
x*x - x - 1 = 0

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

A little more math ...

// create an array of prime numbers from 2 to < limit
// using a sieve algorithm
func primeArray(limit: Int) -> [Int] {
    // 0 and 1 are not primes
    var boolArr: [Bool] = [false, false]
    // rest of array is set to all true
    for k in 1...limit-2 {
        boolArr.append(true)
    }
    let rangeLimit = Int(sqrt(Double(limit)) + 1.5)
    for var n = 0; n < rangeLimit; n++ {
        if boolArr[n] {
            var square = n*n
            while square < limit {
                // these indeces will not be primes
                boolArr[square] = false
                square += n
            }
        }
    }
    var primes = [Int]()
    // each index of a remaining true is a prime
    for (ix, bool) in enumerate(boolArr) {
        if bool {
            primes.append(ix)
        }
    }
    return primes
}

var primes = primeArray(61)
// first line has known primes for comparison ...
// [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59]
// [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59]
println(primes)
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Coming in the fall of 2015 ...
Swift2 replaces println() with just print() that has a newline default. The sort of thing that Python3 did to print(). There are some other syntax changes.
Good news, there will be a Swift 1-to-2 migrator utility to change Swift1 syntax to Swift2 syntax.

serenagrace 0 Newbie Poster

someone mentioned that swift will be open source, does that mean we will be able to get the apple OS for free too

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Apple OSX only runs on Macintoshes, and comes as standard with every Mac, so you never need to buy it. All the upgrades are also free (at least for now).

Lardmeister 461 Posting Virtuoso

I think open source implies that Swift will be developed by and for the Linux community.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.