Categories
Nerd Fun Programming

Emoji Tac Toe Opened Sourced

Happy Father’s Day!

 

To celebrate my 28th Father’s Day I’ve opened sourced Emoji Tac Toe. It’s actually not a big deal to anyone but me. It’s kinda of scary open sourcing code that you wrote alone and without first cleaning it up. But what the heck. If someone can learn something from this code, why keep it locked away. It’s already been on GitHub for a year. It’s not getting any prettier under lock and key.

You can find the source code at github.com/jpavley/Emoji-Tac-Toe2. And you can download the iOS app on the App Store at John Pavley > Emoji Tac Toe.

You can play Emoji Tac Toe on your iPhone, your iPad, and your Apple Watch. (As long as you are running iOS 9.3 or later.)

I guess I should chat a little bit about the code just in case you want to take a peek.

First

I plan on refactoring the code quite a bit. I want to basically refactor it so that the core is separate from the iOS implementation and I can port it easily to the web and to Android. Maybe Windows too. Who knowns! I’m going to start this process by adding unit tests and then by tearing it apart.

Second

I plan on updating the code for iOS 11, including Swift 4 and ARKit. I’ve been meaning to add multiplayer over BlueTooth and MessageKit capabilities. I also want to complete the tvOS and macOS implementations.

Third

The core code lives in the EmojiTicTacToe.swift file. Since there are more emoji than I can count I have cherry picked the 1100 that I wanted to include. This is still too many and I should cut it down further. It’s too many emoji because choosing which emoji to play with is difficult. I can’t use Apple’s keyboard user interface because I can’t restrict it to just showing emoji. And I don’t want to waste my time recreating Apple’s design. Also, this game is not about typing anything so a keyboard doesn’t make sense.

Instead I create an array of emoji and it works very well. iOS is great at dealing with Unicode.

Tic Tac Toe is an ancient game and simple. There only eight winning vectors. So, it’s easy to brute force and just check any board for the eight vectors.

As emoji are text it’s simple to translate a game board into a string and back. Interoperability with messaging and tweeting is free. This is why I love emoji! Rich graphics without the cost of image file management. Once day when operating systems allow custom emoji we’ll stop using PNGs and JPEGs altogether. On that day the web will be more fast and safe than ever!

Given the simplicity of the game, my AI is equally simple. When it’s the AI’s turn, I look for an open cell, look for a blocking move or look for a winning move using the eight winning vectors as my guide. Because tic tac toe is too easy to prevent absolute boredom I add a bit of random error into the AI’s thinking so that if the player is paying attention she can beat the machine.

Four

ViewController.swift contains iPhone/iPad specific code.

I found I needed some iPad specific code to avoid a crash when presenting Apple’s standard share UIActivityViewController. I did not open a radar.

I handle several gestures that I’m sure my players never discover but they are there none the less:

  • A long press on an emoji can trigger an attack if battle mode is enabled. A few emoji will do cool tricks in battle mode. There are several battle mode strategy functions that implement these tricks. My favorite is youWin which lets the other player win.
  • Panning up and down turns sounds on and off. That should be a standard gesture for all games!
  • A shake starts are new game with a random pair of emoji. This is the best way to start a new game as choosing particular emoji is a pain.

Five

NewGameViewController.swift contains the code for the game settings on the iPhone/iPad.

Originally, I had the iPhone and Watch Extension collaborate so that one could control the other. But the effort was not worth the reward. Now the two version are completely independent.

I use a UIPickerView with two components to enable the player to choose two emoji. It’s not bad at all if there were only 20 or 30 emoji. But it’s just too much spinning to find a particular emoji out of 1100!

If the user tries to choose the same emoji for player 1 and player 2 (or the AI) I detect that and have the UIPickerView jump to the next emoji. See ensureRowsAreUnique(component: row:).

To make finding a particular emoji a bit easier I allow the player to jump over groups of emoji in the UIPickerView by tapping on the labels for each player. I’m guessing nobody would ever find this feature but the labels are colored blue to indicate they buttons.

Six

InterfaceController.swift contains the code for a very simple version of Emoji Tac Toe that runs on watchOS. I actually like this version if the game best. No battle mode, no sound, no popovers, no choice of emoji. Just a single player game you tap out on your watch while waiting for the train.

Programming the UI for watchOS reminded me of my VisualBasic days! Each button view has it own handler function. No way to aggregate the touches and dispatch them with a switch statement!

Final Notes

All-in-all this code is pretty rough and need a lot of work. But it does work and hardly ever crashes. So that’s something. There is a half-finished tvOS implementation but I’m going to rethink it so don’t look at it!

I had to delete the sound effect that I didn’t create myself. Your build of Emoji Tac Toe will not sound like mine. But otherwise you are free, within the MIT License constraints, to do what you like with the code.

Categories
Nerd Fun Programming Tech Trends

JavaScript, Swift, and Kotlin Oh My!

This blog post now lives on http://blog.viacom.tech/2017/05/31/the-co-evolution-of-javascript-swift-and-kotlin/ (and it’s much shorter and better!)

 

Categories
Programming Uncategorized

Swift Programming: Filtering vs For Loops

The current version 3.1 has come a long way from the Yet-Another-C-Based-Syntax of the 1.0 version of Swift.

One of the best features of Swift is how functional programming idioms are integrated into the core of the language. Like JavaScript, you can code in Swift in several methodologies, including procedural, declarative, object-oriented, and functional. I find it’s best to use all of them all simultaneously! It’s easy to become a victim of the law of diminishing returns if you try to stick to one programming idiom. Swift is a very expressive coding language and it’s economical to use different styles for different tasks in your program.

This might be hard for non-coders to understand but coding style is critical for creating software that functions well because a good coding style makes the source easy to read and easy to work with. Sometimes you have to write obscure code for optimization purposes but most of the time you should err of the side of clarity.

Apple has made a few changes to Swift that help with readability in the long term but remove traditional C-based programming language syntax that old-time developers like me have become very attached to.

The most famous example was the increment operator:

x++ // add one to the value of x

In modern Swift you have to write:

x += 1 // add one to the value x in Swift

As much as I loved to type ++ to increment the value of a variable there was a big problem with x++! Most coders, including me, were using it the wrong way! The correct way for most use cases is:

++x // add one to the value of x before using x

Most of the time the difference in side effects between ++x and x++ were immaterial, except when it wasn’t and it created hard to track down bugs in code that looked perfectly ok.

So now I’m used to typing += to increment values even in programming languages where ++ is legal. (Also, C++ should rebrand itself as C+=1.)

Another big change for me was giving up for-loops for functional expressions like map, reduce, and filter. As a young man when I wanted to find a particular object in an array of objects I would loop through the array and test for a key I was interested in:

for o in objects {
  if o.id == 12345 {
    // do something
    break;
  }
}

Nothing is wrong with this code—it works. Well, actually there is a lot wrong with it:

  • It’s not very concise
  • I should probably have used a dictionary and not an array
  • What if I accidentally try to change o or objects inside this loop?
  • If objects is a lengthy array it might take some time to get to 12345
  • What if there is more than one o with the id of 12345?
  • This for-loop works but like x++: it can be the source of subtle, hard to kill bugs while looking so innocent.

But I’ve learned a new trick! In Swift I let the filter expression do all this work for me!

let o = objects.filter { $0.id == 12345 }.first!

In that single line of code o will be the first object that satisfies the test id == 12345. Pretty short and sweet!

At first, I found the functional idiom of Swift to be a little weird looking. By weird I mean it looks a lot like the Perl programming language to me! But I learned to stop being too idiomatic and to allow myself to express functional syntax as needed.

For you JavaScript or C programmers out there here is a cheat sheet to understanding how this functional filtering works:

  • let means o is a constant, not a mutable variable. Functional programing prefers constants because you can’t change them accidentally!
  • The { } represents a closure that contains a function and Swift has special syntactic sugar that allows you to omit a whole bunch of typing if the function in the closure is the last or only parameter of the calling function. (Remember in functional programming functions are first class citizen and can be pass around like variables!)
  • $0 is a shortcut for the first parameter passed to your closure. So you don’t have to bother with throw away names like temp or i,j,k,x, or y.
  • .first! is a neat way to get [0], the first element of an array. The ! means you know it can’t fail to find at least one element. (Don’t use the ! after .first unless you are 100% sure your array contains what you are looking for!)

I’m working on a new project, a game that I hope to share with you soon. The game itself won’t be very interesting. I find that I enjoy creating games more than I enjoy playing them so I’m not going to put too much effort in creating the next Candy Crush or Minecraft. But I will blog about it as I work thought the problems I’ve set for my self.

Categories
Nerd Fun Programming

Notes on NSUserPreferences

You can set and get NSUserPreferences from any view controller and the app delegate to they are a great way to pass data around the various parts of your iOS App.

Note: NSUserPreferences don’t cross the iOS/watchOS boundry. iOS and watchOS apps each have their own set of NSUserPreferences.

In the example below you have a class `Bool` property that you want to track between user sessions.

// inside some view controller class

var showAll = true

// inside viewDidLoad()

      if let savedShowAll = NSUserDefaults.standardUserDefaults().objectForKey("savedShowAll") {
          showAllStops = savedShowAllS as! Bool
      }

// inside your action assocated a switch control

        showAll = !showAll
        NSUserDefaults.standardUserDefaults().setObject(showAll, forKey: "savedShowAll")

In the code above…
– The var showAll is the data model for a switch object value
– The string savedShowAll is the key for the stored value
– Use NSUserDefaults.standardUserDefaults().objectForKey() to access a stored value
– Use the if let idiom as the stored value might not exist
– Use NSUserDefaults.standardUserDefaults().setObject() to save the value
– Apparently setObject() never fails! 😀

Categories
Nerd Fun Programming

Code Markup in Xcode

Screen Shot 2016-05-28 at 12.58.13 PM

I’m working on a fairly large Swift project. Actually no, that’s not quite true. I’m working on a Swift project with a ViewController file that is getting disorganized and out of control. If this keeps up I might have a large project on my hands but right now it’s just a single file that is getting larger than I would like.

Apple provides some quick and dirty tools that make it easy to navigate a single file with specially formatted comments in your code. This functionality doesn’t provide automated documentation like Headerdoc. And that’s fine with me. I like how Headerdoc has become a mash up of Markdown and JavaDoc. My code is just not stable enough for documenting yet.

Happily Xcode’s built-in special comment parser is enough in the early stages of development to help me navigate a large file and remember where the bodies are buried.

Xcode supports the following out of the box:

  • MARK: (your text here)
  • MARK: – (section divider)
  • ???: Question
  • !!!!: Warning
  • TODO: Task
  • FIXME: Bug

Xcode’s special comments mark up the function navigation  pop-up menu so that you can find your questions, warnings, tasks, and bugs in your code without a overtaxing your the private neural network in your skull. Unfortunately you can’t add new special comments and they don’t show up in the Symbol Navigator.

(Using the MARK: comment you can simulate adding your own special comments. MARK: doesn’t add the word MARK: in front of navigation items in the way that the other special comments do (TODO, FIXME, etc.). So you can use MARK: NOTE to navigate to notes in your Swift code if that makes you happy.)

I use the following additional special comments to keep my code organized and consistent. (Xcode will just ignore them unless I prefix each with MARK:)

  • NOTE: (when the function name is not enough)
  • HINT: (a non-obvious reminder about a bit of code)
  • DBUG: (end of line comment marking code that probably should be removed eventually)
  • DEMO: (example usage)
    // MARK: -
    // MARK: Storyboard Actions

    @IBAction func rightSwipeGesture(sender: UISwipeGestureRecognizer) {
        // HINT: previous page
        currentTrainIndex -= 1
        if currentTrainIndex < 0 {
            currentTrainIndex = trainCount - 1
        }
        loadContent()
    }  

    @IBAction func leftSwipeGesture(sender: UISwipeGestureRecognizer) {
        // HINT: next page
        currentTrainIndex += 1
        if currentTrainIndex == trainCount {
            currentTrainIndex = 0
        }
        loadContent()
    }

It would be nice if Apple allowed us to personalize code markup in Xcode. But only after search and ranking in the App Store are fixed and a 1000 other higher priories are done!

Categories
Nerd Fun Programming

Fun with Core Graphics and Swift Part 2

Screen Shot 2015-11-09 at 9.24.06 PM

Hey, you have 10 minuets, don’t you?

Then you can add pinch and rotate gestures to our fake-genigraphics app. I didn’t realize it would be this easy. But sometimes Apple’s developer tools engineering team does something amazing–and gesture recognizers are super amazing.

A good way to start is to read the UIGestureRecognizer Tutorial on Ray Wenderlich’s website. I’ve said good things about Ray before. I don’t know him. However, Ray and his team of technical authors just have a way of spelling things out 100 times more clearly than Apple’s developer documentation.

After you’ve read the tutorial open up ViewController.swift in the fake-genigraphics project. Delete the boilerplate code in the ViewController class and replace it with the following code (from the tutorial):

    @IBAction func handlePinch(recognizer : UIPinchGestureRecognizer) {
        if let view = recognizer.view {
            view.transform = CGAffineTransformScale(view.transform,
                recognizer.scale, recognizer.scale)
            recognizer.scale = 1
        }
    }
    
    @IBAction func handleRotate(recognizer : UIRotationGestureRecognizer) {
        if let view = recognizer.view {
            view.transform = CGAffineTransformRotate(view.transform, recognizer.rotation)
            recognizer.rotation = 0
        }
    }

Each of these functions is decorated with the @IBAction tag. That means we’re going to hook them up to events from our project’s Main.storyboard. This part still vexes me. I want to do everything in code and not use drag and drop to wire up events with functions (and properties with variables). Especially since I am left handed and to do a key part of the drag and drop I have to use the control key which only exists on the left side of my nifty Apple Magic Keypad.

Enough whining. Time to drag and drop!

Open up your Main.storyboard in the fake-genigraphics project. In the Object Library on the right find the section near the bottom with all the gesture recognizers. Drag a Pinch Gesture Recognizer out from the library and drop it on the BackgroundView in the storyboard. Now for the hard part: In the Document Outline on the left control-drag the Pinch Gesture Recognizer entry up and drop it on the ViewController entry. On the pop-up menu that suddenly appears choose Sent Actions Handle Pinch. (So weird).

Do these same steps again with the Rotation Gesture Recognizer. What you are doing is connecting events from the gesture recognizers to the functions in the ViewController marked with @IBAction.

Guess What? You’re done! Run your app in the simulator and on your iPhone or iPad. You can now zoom in and out and rotate the Background View like a pro. Notice how responsive and smooth the animation is. Alas there seems to be limits on how far you can zoom out. And you can’t rotate and zoom at the same time. I have trouble with rotating with my left hand. I’m convinced that nobody at Apple is left handled!

Categories
Nerd Fun Programming

Fun with Core Graphics and Swift

Screen Shot 2015-11-07 at 12.15.12 AM

A long time ago in a galaxy far, far away… I was a computer graphics artist. Specifically I was a Genigraphics
console operator. I worked the night shift creating illustrations and slides with vector graphics for big corporations. This was the early 1980s and fast, cheap personal computers with color graphics had not quite been invented yet. Later when I learned to program the Apple Macintosh I had a head start–I had created hundreds of vector images using computer graphic primitives by hand! The ability to draw lines, circles, and rectangles with code blew my mind.

I’m thinking it would be fun to do some graphics exercises with Swift and Apple’s Core Graphics. Maybe recreate some of those Genigraphics images from 30 years ago. Somewhere in the basement I have a box of 35mm slides and 8″ floppy disks. Probably not readable but I should be able to create a few images from memory. Genigraphics was the ancient ancestor of PowerPoint and Keynote. Every element in an illustration or on a slide had to be created from a graphic primitive. A gradient color fill was created with 30 or 40 overlapping rectangles, each with an incrementally different color.  And remember all the primitives were created by a human hand!

One of the most time consuming effects involved creating a grid for a background. It involved much duplicating, aligning, and counting.

So let’s create a clunky Genigraphcis grid in Swift using Core Graphics and display it in a UIView on and iOS device!

Launch Xcode and create a new iOS single view application. Make sure you choose Swift as the language. It doesn’t matter what you call your app. Run the new blank app just to make sure Xcode did it’s job.

Kill the app and go back to Xcode. Create a new iOS Cocoa Touch Class source file. Call it BackgroundView and make it a subclass of UIView. Go to your main.storyboard and select the View in your View Controller. In the Identity Inspector set the class of the View to BackgroundView.

Run the app again just make sure it builds and then kill it and return to Xcode.

Select BackgroundView.swift. You should see a drawRect function provided by Apple. Delete all the comments so it’s ready for some grid code…

override func drawRect(rect: CGRect) {

}

This function is called whenever iOS needs to paint your view on the screen. The rect is the area that needs to be painted. The first time drawRect is called the rect is the same size as your view. Later on when drawRect is called the rect is just the area of the view that needs to be updated. So I get the view width and height from the bounds. I’m also assuming the origin (left, top corner) is always 0,0. Add the following code to your drawRect function so you can get the the bounds width and height and compare it to the rect (technically called the “dirty rect” because that is the part of the view that needs to redrawn).

        let viewWidth:CGFloat = self.bounds.width
        print("viewWidth \(viewWidth)")
        print("rect.size.width \(rect.size.width)")
        
        let viewHight:CGFloat = self.bounds.height
        print("viewHight \(viewHight)")
        print("rect.size.height \(rect.size.height)")

I like to define all my important variables together near the top of my functions because I always know where to find them. Swift let’s you declare and define variable throughout the code. (I only use that freedom for unimportant “throw away” variables that are used inside loops and other control structures.)

Add the code to define your gridlines starting points, lengths, and line width.

        let x1:CGFloat = 0.0
        let x2:CGFloat = viewWidth
        
        let y1:CGFloat = 0.0
        let y2:CGFloat = viewHight

Core Graphics likes all your coordinates to be CGFloats. Since the resolution of an iOS device can be just about anything size these coordinates represent an idealize space as points. On a high resolution iOS device, like an iPhone 6s Plus you’re going to get 3 pixels for every point. My iPhone 6 Plus has a resolution of 1242 × 2208 but Core Graphics gives me 414 × 736 to work with. I’m just going to live with that for now.

I want a nice square grid so I use the either the viewWidth or viewHeight (which ever is smaller) divided 15 as the length of a grid cell.

        let cellLength:CGFloat = min(viewHight, viewWidth) / 15
        print("rowHeight \(cellLength)")

Now it’s time to set the style of our lines: color and width. As I recall Genigraphics only had 64 colors or maybe 128. I’ll figure that out next weekend. In the meantime I choose blue with a width of 2.

        let lineWidth:CGFloat = 2.0
        
        let context = UIGraphicsGetCurrentContext()
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        
        let components: [CGFloat] = [0.0, 0.0, 1.0, 1.0]
        let color = CGColorCreate(colorSpace, components)
        
        CGContextSetLineWidth(context, lineWidth)
        CGContextSetStrokeColorWithColor(context, color)

Wow! That’s a lot of code just to set the color and line width. It’s a little complicated because Core Graphics is context-based. You have to get the current graphics context and modify it to draw. In the code above I’m also creating a color the hard way via a color space and RGBA (Red Green Blue Alpha) color values. All this work will let me have a fine degree of control of the color of the gridlines later on.

Finally, I’m going to draw my horizontal and vertical gridlines!

        // draw horizontal lines
        var i:CGFloat = 0.0
        repeat {
          
            CGContextMoveToPoint(context, x1, cellLength + i)
            CGContextAddLineToPoint(context, x2, cellLength + i)
            
            i = i + cellLength
            
        } while i < rect.height - cellLength
        
        
        // draw vertical lines
        var j:CGFloat = 0.0
        repeat {
            
            CGContextMoveToPoint(context, cellLength + j, y1)
            CGContextAddLineToPoint(context, cellLength + j, y2)
            
            j = j + cellLength
            
        } while j < rect.width - cellLength

I’m just fooling around at this point so I don’t know if two repeat loops is the most efficient way to draw a grid. Right now I’m just happy to see a grid show up. I’ll optimize it later–if needed! To draw my lines I start at 0 and draw each line a cellLengh apart. CoreGraphics is a bit like Logo’s turtle graphics: I have to add drawing commands to the context, building up the image step by step behind the scenes.

If you run the code that this you will see nothing! Go ahead… I dare you!

That’s because you need to tell the graphics context to blast your drawing commands from the context on to the view. One line of code does it.

        CGContextStrokePath(context)

If you have been typing along you now have a custom UIView that draws a grid properly no matter now you hold your iPhone.

If you want to see the grid on your storyboard add

@IBDesignable

just above the class declaration. But be careful! Buggy Core Graphics rendering can freeze up Xcode. (It happened to me while writing this code.) I keep @IBDesignable commented out until I know my drawing code is working.

You can find all the code on GitHub.

Next week I’ll add some more complex drawing in the OG Genigraphics style. This is a good start for your own explorations. Have fun and don’t worry! You can’t blow up your computer by writing code.

Categories
Nerd Fun Programming Uncategorized

The Secret to Swift is Enums

I’ve found the CS193P (Developing iOS 8 Apps with Swift) iTuneU class really helpful in wrapping my old Objective-C head around Apple’s new Swift programming language. Yes, I know we’re at iOS9 but the fundamentals of the class are still relevant and coaxing the code to compile in iOS 9/Swift 2.0 is a fun little last in and of itself.

The big revelation for me is how core Swift’s enums are to understanding and using the language properly. When Apple decided to improve it’s development environment it could have done so in a million different directions. Apple could have just patched up Objective-C. Apple could have moved over to Java or Scala or even JavaScript. (I was hoping for  JavaScript as Node.js and ECMAScript 6 have proved that JavaScript is an industrial strength language with a real future.)

So when I learned that Apple created a new language for iOS and Mac OS X (and now WatchOS and tvOS) application development I was intrigued and disappointed and hopeful all at the same time. Many parts of Swift seems easy and cool but some parts were down right intellectually challenging: Classes and Structs? Super fancy Enums? Optionals? Strings with out a simple function to get their length? What the heck is going on here?

Swift seemed promising. But it was also changing rapidly over the last year. I fooled around with it but when I hit optionals and weak references I realized the language was not going to sugarcoat the problems of null pointers and memory management–it was trying to make them more tractable.

Optionals were especially vexing. var amount: Double? was not a Double. It was a potential Double. Amount! had better be a Double or it would crash my program. If it was’t for Xcode’s automated static code analysis I never would have been able to put the ? and ! in the right places after the right variable names. And I didn’t like that feeling.

But then I found CS193P and Professor Paul Hergarty’s remarkable ability to explain things simply.

Enums in Swift are amazing little machines. They have little in common with C Enum other than you can use them to define collections of related constants. Enums are types with values that evaluate to themselves. But  you can associate a “raw value”, like a number or a string, or more a advanced value, like Tuples or Arrays or Dictionaries. And with advanced types come functions and closures.

Yikes. These are not your father’s Enums. As Professor Hergarty’s says, Swift Enums are types used for when you want to switch between values. And, point of fact, Swift Enums are defined like a Switch structure with case statements. Each of the cases, except with raw values, can be of different types.

And boom! That explains Optionals. When you have a value that could be nonexistent or of some type, an Optional is just an Enum that wraps up it safely so you can pass it around without crashing. ? and ! are just syntactic shortcuts for accessing the different states an Optional variable might be in. Imagining that Optionals are Enums gave me the handle my mind needed to process the whole concept.

In CS193P Professor Paul Hergarty uses an Enum to power his “Calculator Brain”. In any other programming language an Enum would be used to make the code more readable. But in Swift you can use an Enum as the glue to associate states with types with functions. I have a feeling that this Enum-driven mechanism is the cleanest way to write a Swift state machine. It’s still a little rough around the edges and verbose. But it’s a super reusable pattern good not only for the mathematical operations of a calculator but for managing the states of a web server, business application, or game.

//: Playground - noun: a place where people can play

import UIKit
import Foundation

class CalculatorBrain {
    
    enum Op: CustomStringConvertible {
        case Operand(Double)
        case BinaryOperation(String, (Double, Double) -> Double)
        
        var description: String {
            get {
                switch self {
                case .Operand(let operand):
                    return "\(operand)"
                case .BinaryOperation(let symbol, _):
                    return symbol
                }
            }
        }
    }
    
    var opStack = [Op]()
    var knownOps = [String:Op]()
    
    init() {
        func learnOp (op: Op) {
            knownOps[op.description] = op
        }
        
        learnOp(Op.BinaryOperation("*", *))
        learnOp(Op.BinaryOperation("+", +))
        learnOp(Op.BinaryOperation("-", {$1 - $0}))
        learnOp(Op.BinaryOperation("/", {$1 / $0}))
    }
    
    func evaluate() -> Double? {
        let (result, _) = evaluate(opStack)
        return result
    }
    
    func evaluate(ops: [Op]) -> (result: Double?, remainingOps: [Op]) {
        if !ops.isEmpty {
            var remainingOps = ops
            let op = remainingOps.removeLast()
            
            switch op {
            case .Operand(let operand):
                return (operand, remainingOps)
            case .BinaryOperation(_, let operation):
                let op1Evaluation = evaluate(remainingOps)
                if let operand1 = op1Evaluation.result {
                    let op2Evaluation = evaluate(op1Evaluation.remainingOps)
                    if let operand2 = op2Evaluation.result {
                        return (operation(operand1, operand2), op2Evaluation.remainingOps)
                    }
                }
            }
        }
        return (nil, ops)
    }
    
    func pushOperand(operand: Double) -> Double? {
        opStack.append(Op.Operand(operand))
        return evaluate()
    }
    
    func popOperand() -> Double? {
        if !opStack.isEmpty {
            opStack.removeLast()
        }
        return evaluate()
    }
    
    func performOperation(symbol: String) -> Double? {
        if let operation = knownOps[symbol] {
            opStack.append(operation);
        }
        return evaluate()
    }
    
    func showStack() -> String? {
        return opStack.map{ "\($0)" }.joinWithSeparator(" ")
    }
}

var cb = CalculatorBrain()

print(cb.knownOps)

cb.showStack()
cb.pushOperand(1)
cb.pushOperand(2)
cb.performOperation("+")
cb.pushOperand(3)
cb.pushOperand(4)
cb.performOperation("/")
cb.pushOperand(5)
cb.pushOperand(6)
cb.performOperation("*")
cb.pushOperand(7)
cb.pushOperand(8)
cb.performOperation("-")
cb.showStack()

You should watch all the videos in CS193P to get the full picture. But in the meantime I’ve created a simplified version of Professor Hergarty’s CalculatorBrain suitable for a Swift Playground (above). As you fool around with the code keep in mind the following points:

  • CalculatorBain is a class and when it’s instantiated it’s initializer creates a dictionary of operations that it knows about based on type. You can add more known operations by writing a little code in one place. In the sample code the operations for addition, subtraction, division, and multiplication are written very concisely using Swift’s shortcut syntax for closures with default parameter names. (This reminds me of the best features Perl.)
  • The custom type Op is an Enum that is self documenting and has values associated with either a Double (for operands) or a Dictionary (for operations indexed by name). So simple lookups via a case statement are all that is needed to process input and output a result.
  • The two Evaluate functions are recursive, calling each other until every operand or operation needed in the Ops stack is consumed. Evaluate basically does this:
    • Until the Ops stack is empty pull an item off the end of the stack.
    • If that item is an Operand return it and the remainder of the Ops stack.
    • If that item is an operation dig into the Ops stack until you can get two operands and then execute the function associated with the operation using the operands.
    • The return the result with the remaining Ops stack.
  • If I had to write this code without using recursion and without Swift’s muscular Enums, well, there would be a lot more code and it would be more “hard coded”.

The only improvement I can think of would be to declare the known operations as a literal Dictionary. But the Swift compiler isn’t ready for that and complains: “Expression was too complex to be solved in reasonable time”. I guess if Swift can’t do something swiftly it doesn’t want to do it at all!

 

Categories
Programming

Nothing Changes More Swiftly than Apple’s Swift Syntax

Screen Shot 2015-09-24 at 6.39.39 PM
Look at that beautiful Apple Swift code on the right with closures and shorthand argument names! Make’s me smile every time!

I’m enjoying the Stanford University class CS193P: Developing iOS 8 Applications with Swift. It’s free on iTunes U and the instructor Paul Hegarty knows his stuff. He’s a great explainer. I like how first he writes some code in a naive way and then fools around with it, getting it to work and then reworking it like a sculptor with clay. That’s how real programmers work. We write a rough draft of the code, make sure we understand it and then “refactor” it until we’re no longer embarrassed to share it on GitHub.

But even though the class was recorded in 2014 and updated in June of 2015 it’s aging rapidly. We’re already working with Xcode 7 and iOS 9. And all the little minor changes and improvements are adding up.

One problem you might run into is with the second video: More Xcode and Swift, MVC. In this lesson Professor Hegarty wants to show how we can use a form of polymorphism to write clean code. Specifically with Swift supports something that Objective-C did not! In Swift we can have class functions with the same name but different signatures. In the example in the lesson he shows how we can write two versions of performOperation–one that takes two Doubles as arguments and another that takes only a single Double as an argument. Very cool…

Unfortunately this code no longer compiles.

There is an explanation on Stack Overflow (if you can find it). But it’s not really clear as there are a couple of solutions. Perhaps the best solution, like so much on the human side of computer programming, is a matter of taste.

Here is the code and the fix:

    // these functions won't compile with Swift 1.2 and above
    func performOperationWith(operation: (Double, Double) -> Double) {
        if operandStack.count >= 2 {
            displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
            enter()
        }
    }
    
    func performOperationWith(operation: Double -> Double) {
        if operandStack.count >= 1 {
            displayValue = operation(operandStack.removeLast())
            enter()
        }
    }
    // these functions will happily compile
    func performOperationWithTwoOperands(operation: (Double, Double) -> Double) {
        if operandStack.count >= 2 {
            displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
            enter()
        }
    }
    
    func performOperationWithOneOperand(operation: Double -> Double) {
        if operandStack.count >= 1 {
            displayValue = operation(operandStack.removeLast())
            enter()
        }
    }

Because Swift is smart about classes written in Objective-C that you are subclassing from, it forces those subclasses, in this case UIViewController, to obey Objective-C’s limitations. One of those limitation was not allowing polymorphism for methods with the same name but different arguments.

The code is a little uglier, because there is slightly more of it, but it smart of Apple to be as compatible with Objective-C as possible. At least for a few more years 🙂