Swift Fun with ArraySlice

There is a lovely article by Luna An describing ArraySlice objects in more detail than I do here. It covers Swift 3 at the moment, and you should note that Swift 4 includes support for single-ended ranges, so you can create slices ala [..<count].

I found a good use for an ArraySlice while trying to find quartiles in a set of data.

The problem of finding each quartile is essentially the same problem of finding the median from three different data sets, one being the original input set, the other two being the upper and lower half of the set after removing the original median element, if it exists.

Here, I use findMedian to perform all three tasks. I found that I had to do a bit of extra work because the array slice is not indexed starting at zero. I wonder why they chose to implement slices in this way?

import Foundation

func findMedian(_ data: ArraySlice<Int>) -> (Int, Int, Int) {
    let index1 = (data.count-1)/2
    let index2 = data.count/2
    let sliceIndex1 = index1 + data.startIndex
    let sliceIndex2 = index2 + data.startIndex
    let median = (data[sliceIndex1]+data[sliceIndex2])/2
    return (sliceIndex1, sliceIndex2, median)
}

let data = [0, 1, 2, 5, 11, 17, 19, 21]

let X = data[0..<data.count]
let (q2Index1, q2Index2, Q2) = findMedian(X)
let L = data[0..<q2Index2]
let U = data[(q2Index1+1)..<data.count]
let (_, _, Q1) = findMedian(L)
let (_, _, Q3) = findMedian(U)

print(Q1)
print(Q2)
print(Q3)

 

Command Design Pattern in Swift

It is the summer of Swift.

I was perusing some wonderful design patterns from Oktawian Chojnacki, and I decided to play around with the Command pattern. The Command pattern represents commands as objects to go between a Caller, which references the commands, and a Receiver, which is referenced by the commands.

I’m reminded of a game :

RoboRally

Here, each command object operates on a Robo, telling it to make a single move. The commands are collected into a program.

//: Command - Represents commands as objects.

import Cocoa

class Robo : CustomStringConvertible {
    let name : String
    var description: String {
        return name
    }

    init(name: String) {
        self.name = name
    }
}

protocol RoboCommand {
    func execute(robo: Robo)
}

class TurnRight : RoboCommand {
    func execute(robo: Robo) {
        print("\(robo) turns right ➡️")
    }
}

class TurnLeft : RoboCommand {
    func execute(robo: Robo) {
        print("\(robo) turns left ⬅️")
    }
}

class GoForward : RoboCommand {
    func execute(robo: Robo) {
        print("\(robo) goes forward ⬆️")
    }
}

class RoboProgram {
    let robo : Robo
    var commands : [RoboCommand] = []

    init(robo: Robo) {
        self.robo = robo
    }

    init(robo: Robo, commands: [RoboCommand]) {
        self.robo = robo
        self.commands = commands
    }

    func execute() {
        for command in commands {
            command.execute(robo: robo)
        }
    }
}

let robo = Robo(name: "Mikey")
let program = RoboProgram(robo: robo)
program.commands.append(GoForward())
program.commands.append(TurnLeft())
program.commands.append(GoForward())
program.commands.append(GoForward())
program.commands.append(TurnRight())
program.commands.append(GoForward())

program.execute()

The first draft of this code had the Commands store their target Robo in a property. I realized a problem with this in that my program would accept commands for any Robo, when only one Robo belongs to the program. My solution for this was to give control of the command target to the program itself.

Of course, now the commands are little more than glorified functions, which can be stored in arrays in Swift anyway.

Swift Dictionary Reduce

Why is it so hard to find examples of Swift dictionary reduce operations? Examples for arrays abound :

let countme = [1, 2, 3, 4, 5]
let sumall = countme.reduce(0){$0+$1}
// sumall is now 15

See this if you’re looking for a detailed HowTo.

But dictionary is the more advanced problem. How do I reduce when I have keys and values?

The key here is to note that a dictionary yields the contents of its sequence in tuples containing pairs of values. We still have our familiar $0, $1 arguments from reduce as above, where $0 is the partial sum and $1 is the individual element value. But now $0 and $1 are both tuples, and you get to their contents through $0.0, $0.1, $1.0, and $1.1.

let namesNumbers = ["Mike":21, "Bruce":25, "Alice":27]
let (bigname,bignumber) = namesNumbers.reduce(("",0)) 
  {return ($0.0 + $1.0, $0.1 + $1.1)}

This example concatenates the strings and adds the integers, and the two separate data types just happen to use the same symbol for the two operations.

Book Critic

I don’t like to step on anyone’s work. Having taught university computer science for a decade, I can tell you that it is difficult to present technical material in a way that is both correct and engaging. My students’ surveys remind me every semester that 100% satisfaction is elusive. But I want to critique the writing style of a book on Swift that I just browsed at Barnes and Noble. If you are easily tripped up on vague or ambiguous descriptions, please know that we share this obsessive trait.

See the section subtitled Building Blocks of Swift, in bold? It establishes the very basic programming concept of named storage, called variables in most material even if their values never change. The unchanging named values are also called constants. In Swift, these named values are declared with the syntax var variableName=value for variables and with let constantName=value for constants.

These are my complaints :

  • The first paragraph explains variables and constants, but only gives the keyword var for variables. What about let for constants? This leaves me hanging.
  • The sample code below P1 is obviously not illustrative of the example described, even though it prefaces the code with “as shown in this example:”.
  • The sample code below P1 contains errors! The reassignment of the constant will break at compile time. Syntax errors, while useful for examples, must be flagged clearly so that the reader does not struggle trying to figure out the code!
  • The last example in that section says that you can omit the var keyword, yet we clearly see the var keyword in the example code given. It is more clear to say that we can omit additional var keywords when declaring multiple variables.

So, buyer beware.

CERT, C, and Swift

Swift does not do implicit type conversions between integers of different sizes and signages. By contrast, Java does implicit conversion, but with less risk of unexpected effects due to the lack of unsigned integer types. C, that dinosaur, has a strange and secret show behind every elementary school math operation.

Why is type conversion confusing? I’ll use C as my example. CERT has some of the best low-level down-and-dirty descriptions of the language, so I’ll be borrowing heavily from their examples.

We’ll start with an easy one: Promotion. During arithmetic, everything is automatically promoted up to int or uint (32 bits on most platforms) in order to prevent overflow. It is curious that they don’t promote to something bigger (long), but x86 assembly uses 32-bit registers most of the time, so it’s a natural fit.

        // Example Apple : Integer Promotions
        unsigned char appleCharOp1, appleCharOp2, appleCharOp3;
        unsigned char appleCharResult;
        unsigned char appleCharWrongResult;

        appleCharOp1 = 80;
        appleCharOp2 = 70;
        appleCharOp3 = 100;
        appleCharResult = appleCharOp1 * appleCharOp2 / appleCharOp3;
        appleCharWrongResult = (unsigned char)(appleCharOp1 * appleCharOp2) / appleCharOp3;

If we run this in the debugger, using the lldb command type format add –format “unsigned dec” “unsigned char” for clarity, we see the following:

(lldb) frame variable

(unsigned char) appleCharOp1 = 80

(unsigned char) appleCharOp2 = 70

(unsigned char) appleCharOp3 = 100

(unsigned char) appleCharResult = 56

(unsigned char) appleCharWrongResult = 2

The correct answer is the result of being able to hold the intermediate product, 5600, in a 32-bit variable. If you truncate the intermediate product to 8 bits, you get 0xE0, which is 224. Divide this by 2 gives you after rounding.

Mind you, the end result is that you get the expected answer as long as you don’t stick a weird cast in the middle like I did there. But here is an example where you get the wrong answer without any extra work:

        // Example Cantaloupe
        unsigned int cantaloupeInt1 = UINT_MAX / 4;
        unsigned int cantaloupeInt2 = UINT_MAX / 8;
        unsigned int cantaloupeInt3 = UINT_MAX / 16;
        unsigned long long cantaloupeLongLong1 = cantaloupeInt1 * cantaloupeInt2 / cantaloupeInt3;

Results are

(unsigned int) cantaloupeInt1 = 1073741823

(unsigned int) cantaloupeInt2 = 536870911

(unsigned int) cantaloupeInt3 = 268435455

(unsigned long long) cantaloupeLongLong1 = 10

That’s the wrong answer. You get the right answer if you cast each term to (unsigned long long).

There are many other factors to C integer conversion, such as precision and rank, but these examples suffice to show why it’s a tricky subject.

Enter Swift’s design choice. If you try the same basic code in Swift :

let cantaloupeOp1 : UInt32 = UInt32.max / 4;
let cantaloupeOp2 : UInt32 = UInt32.max / 8;
let cantaloupeOp3 : UInt32 = UInt32.max / 16;
var cantaloupeResult : UInt64 = cantaloupeOp1 * cantaloupeOp2 / cantaloupeOp3

It simply refuses to compile. The operations on the right are legal, but the assignment is not.

Swift is Here to Stay

There are a few pockets of the internet complaining that Swift is not ready for production yet. I dive into these half expecting to see complaints about the changes in Swift 2.2, the rapidly changing standards, etc. Instead, those professional developers who are complaining are warning about lack of binary compatibility between old and new frameworks.

I am not deterred. I’m into Swift now.

This post is short on content. The plan is to follow Apple’s guide to grok basic syntax, followed by Ray’s guide on style to get the latest and greatest best-practices.

After that, the pickin’s get slim because I’m jonesing for Metal tutorials. Good news is that Jacob Bandes says that it makes more sense than OpenGL or CUDA. We shall see, we shall see.