Archive for the ‘Challenge’ Category

The knee-jerk else-clause

I’ve gotten into several heated discussions recently (I wouldn’t call them arguments or fights as no blows were exchanged and we departed as friends) about whether an if-statement should always include a balancing else clause in languages where it is not mandated by a ternary if form.

My feeling is a firm “no”.

Let me attempt to represent the opposing viewpoint. As far as I can tell, the “yes” faction believes that as proper diligence, an else clause should always be added to address both truth scenarios, even if the clause is populated with nothing other than a comment saying “this clause intentionally left blank”. It promotes a consistent inspection of all possible cases, on par with a switch statement requiring full coverage.

I firmly disagree. In my opinion, if-statements boil down to three scenarios:

  • Special CasingAction that applies solely to certain logic conditions, where the absence of those conditions has no effect in the logic. In such case, I recommend to skip the else. There’s no point to it as the flow of execution continues past the additional steps introduced by the if-statement. Adding an else statement removes the clarity of the step-by-step logic and reduces the weight of the special casing in understanding the code.
  • Either-Or: Separate actions of approximately equal weight that apply to both outcomes. If statements are naturally biased towards the positive clause. If both statements are weighted the same, consider refactoring to switch. Even if the switch is ordered (as it must be in some fasion), a switch-statement reduces the emphasis given to either outcome. If both cases are quite large, consider breaking out functionality to dedicated methods. Further, if the logic overlaps between both cases, consider localizing the conditions closer to the differences, even if the test may be applied several times.
  • One case complex, one case simple: Actions that are of disparate impact or weight, where one clause greatly exceeds the complexity of the other, I always place the more complex clause first when used in an if-statement to emphasize the positive path. At the same time, if the simple case is non-trivial, this is an opportunity to consider whether the logic should be broken up or refactored in some way. If an if-clause is so significantly big that it takes up the majority of a method implementation, perhaps you should be using early return for the lighter condition and promoting the more complex logic to the main method body. To me, a heavy complex if-clause usually signifies an opportunity to refactor.

Given these styles, I don’t see any reason, whether from code-reading clarity or a strict adherence to potential future expansion, to automatically include else-clauses as a mandatory part of a coding style. They add heaviness without real functionality and speak to a philosophy of form weighed over functionality. Code should be light, clear, and direct. Mandatory-else is none of those things.

Am I wrong? Go ahead, convince me otherwise. I’m listening.

Cleaning up doc comments for formatted commits

I’m working on a proposal to introduce CountedSet, cousin to NSCountedSet, to Swift. This kind of type involves a massive amount of doc comment content. I decided to adapt the comments from Cocoa Foundation (for NSCountedSet) and Swift Foundation (for Set) as part of my coding and quickly found how ridiculous it was to do this by hand.

At first I tried to write an Xcode “reflow doc comments” extension but as I found in the past, Xcode extensions are a dreadful pain to program and debug. It really wasn’t worth doing this (although it would be my preferred workflow for use) in terms of spending my time well.

Instead, I decided to create a simple playground. I’d paste my Swift file into a known Resources file (in this case, test.swift, although I’m sure you can come up with a better name than that if you use this). I’d process the text with a simple playground implementation and print to stdout.

It was an interesting problem to solve and one that took slightly longer than I anticipated. It’s also one that’s only partially complete. The log jams involved looking ahead at the next line to decide when each blob of text was complete so it could be reflowed, preserving paragraph breaks in the comments, respecting code blocks, and leaving any in-file code intact. Reflowing the words was much easier. I’m sure you’ve written that part of it in any number of algorithms and intro-language classes.

The parts I didn’t tackle were the special formatting required for doc comment keywords, like - Parameter, - Returns, - SeeAlso, and so forth. The associated lines for these items must be reflowed with proper indentation so the Quick Help parser can properly parse them. I leave that for another day because they are relatively minor work compared to reflowing long and complex doc comments as a whole.

I’ve put my code up on Github if you want to offer improvements, fixes, or feedback:

 

Carrying user-sourced code forward in Swift Playgrounds for iOS

Had a really neat challenge today, as a Slack-buddy attempted to work with Apple’s exquisitely insufficient Playground Book documentation. His goal was simple: he wanted to be able to incrementally grow and test code from page to page, copying the user’s work as they moved on.

In theory, Swift Playgrounds for iOS enables you to build books where your reader/student incrementally builds code. Each page introduces a new concept, a new tweak, or a new approach. It’s a great way to layer each lesson on a previous take, or to take one lesson and branch it out to multiple endpoints.

You can either build, build, build to one big story or take one core concept and show many different ways to apply it. Either way, you want to be able to bring code — whether from the most recently edited page or from a shared core page — forward, so the reader/student can further engage with it, edit it, and make it fit with each page’s challenge.

Implementing “code forwarding” (I just made up that term) proved trickier than expected. Playground book workflow is often “understood” (that is, you have a deep understanding of what’s required because you’ve worked with it a lot or you’ve poked around at Apple’s examples or reversed engineered to see how things work) rather than explained step by step in the official docs. Because of this, he ran into several roadblocks along the way.

  • First among these, is that Apple does not provide a Playgrounds Book Author tool for Mac. You have to build your books by hand, going through the specs and hoping that each iteration works. Most of the time it does. Sometimes, maddeningly, it does not.
  • Second, you have to transfer the book to the iPad for each test (I use AirDrop™), and guess at what went wrong if it doesn’t work. When testing a series of book-based exercises, you have to either hard-code each “success” sequence (and there’s no way to set a “I am debugging/developing this book” flag) or actually do the coding, which can take a lot of time, especially if you’re debugging page 7 and you have to work through the exercises on page 1 – 6 for each test of page 7.
  • Finally, if your book is even a little out of spec with what Swift Playgrounds for iOS expects, it’s going to die without much feedback or explanation, leaving you scratching your head, cursing Dev Tools (but we really love you guys, we do), or otherwise venting frustration.

I wasted a bunch of hours because I wanted to make this work. And finally, I managed to get things working to my satisfaction. I thought I’d take the time to write things up to save you some bother. Here are a few things I learned while deep diving into today’s experiments.

The Zen of User Code

Code-forwarding allows you to propagate user-sourced/user-edited code from an earlier page in a playground book to a later page in a playground book. When you code-forward from a “source” to a “destination”, Swift Playgrounds for iOS makes a copy of the earlier code and places onto the current page.

That code is copied once and you aren’t given the option to re-copy unless you reset the page. Every page in Swift Playgrounds offers a reset option in the ellipsis menu, but its discoverability is low. Apple expects each reader/student to work through exercises linearly, progressing only when each previous problem is solved. This means that you don’t get “live” updates by popping back and making new changes to the source page. The destination copies once.

That also means you cannot apply code-forwarding until your page is set as complete. By “complete”, I mean that the book’s source code and Swift Playgrounds accept that the reader/student has done sufficient work to move forward and progress to the next page/exercise.

This usually happens by executing a page epilogue. The epilogue tests the state of the page’s data, determines if the problem was solved (for example, whether the robot reached the end square and the code progressed to a hidden portion containing this test), and then updates a user assessment. Unless a page’s assessment status is “passed” (that is, done), the reader/student is not offered code copying on the following page.

This is built into Swift Playgrounds for iOS, and is an underlying assumption on how progressive learning plans operate. It’s a critical pathway for building page-by-page progress and enabling code-forwarding. This is why the following snippet includes its bit of hidden code. This code allows a user to pass, that is receive a passing grade/assessment for the page, without doing any more work than running the current page:

//#-copy-source(id1)
//#-editable-code 
func foo() {
    // ... starter code here
}
//#-end-editable-code
//#-end-copy-source

//#-hidden-code
import PlaygroundSupport
PlaygroundPage.current.assessmentStatus = 
    .pass(message: "Great job!")
//#-end-hidden-code

Building Code-Forwarding

The preceding code incorporates two essential parts of using a copy-source markup area.

  • First, is the actual tagged copy-source code. This delimits the code that gets copied forward to one or more other pages. Make sure to mark it editable when you want to present a challenge requiring end-user-reader modification. You can omit editable tags when you want the next step or branches to start with code you source yourself. It’s an unusual approach but it’s not illegal to do so.
  • Second, is the hidden assessment update. Normally you’d use more sophisticated logic to determine whether a reader/student has met those challenges laid out in the current page before allowing them to .pass or .fail. When you just want to demonstrate core functionality, make it clear in your marked-up write-up that the user must run the code before continuing. Use the approach in this code to “pass on first run” for demonstration. You’ll probably want to update the message to something along the lines of “Great! You’ve seen this work, move to the next page to start making changes.”

Building The Destination

Crafting a destination page is trickier than laying out acopy-source area: You must update your page’s manifest as well as its content source. The manifest will expect properly internationalized source strings. That means at a minimum, a code receiving page will need a Contents.swift file, a Manifest.plist file, and a PrivateResources folder with at least one localized lproj folder (in my case, en.lproj), which in turn holds the ManifestPlist.strings file.

Here’s what a simple manifest looks like for a copying destination. Keep in mind that each value entry for the CodeCopySetup keys is actually a placeholder for localization.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CodeCopySetup</key>
	<dict>
		<key>CopyCommandButtonTitle</key>
		<string>CopyCommandButtonTitle</string>
		<key>DefaultCommandButtonTitle</key>
		<string>DefaultCommandButtonTitle</string>
		<key>NavigateCommandButtonTitle</key>
		<string>NavigateCommandButtonTitle</string>
		<key>NotReadyToCopyInstructions</key>
		<string>NotReadyToCopyInstructions</string>
		<key>ReadyToCopyInstructions</key>
		<string>ReadyToCopyInstructions</string>
	</dict>
	<key>Description</key>
	<string>Description</string>
	<key>LiveViewEdgeToEdge</key>
	<true/>
	<key>LiveViewMode</key>
	<string>VisibleByDefault</string>
	<key>MaximumSupportedExecutionSpeed</key>
	<string>Fastest</string>
	<key>Name</key>
	<string>Name</string>
	<key>PlaygroundLoggingMode</key>
	<string>Off</string>
	<key>Version</key>
	<string>1.0</string>
</dict>
</plist>

I followed Apple’s example in my ManifestPlist.strings file, so the English expressions aren’t terribly exciting. The Name field used in the manifest is spelled out in addition to the button text:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CopyCommandButtonTitle</key>
	<string>Copy My Code From the Last Page</string>
	<key>DefaultCommandButtonTitle</key>
	<string>Start Coding on This Page</string>
	<key>Name</key>
	<string>Copying Text from the Previous Page</string>
	<key>NavigateCommandButtonTitle</key>
	<string>Return to Previous Page</string>
	<key>NotReadyToCopyInstructions</key>
	<string>Be sure to complete the previous page before you move on to solving the next step.</string>
	<key>ReadyToCopyInstructions</key>
	<string>You can bring over your algorithm from the previous page to continue improving it.</string>
</dict>
</plist>

Here, each possible assessment state and action is given a human-readable form. I was unable to make the system “default” to the items mentioned in the Playground Page Manifest documentation (such as “Copy my code” and “Start with provided code”). I’m sure if I tried hard enough, I could have gotten this working per the docs but I didn’t have the time to push.

In building the code-destination contents, link each identifier you used in the source (it’s id1 in this example but it can be any key you want to use) and the page to copy from (Page1). This page names comes from the name of the playgroundpage file hosting the user-edited or user-sourced content.

You must mention the page because you may keep enhancing the same progression of code from page to page, while using a single identifier. If you start on page 1, update on page 2, when you get to page 3, you want to copy from the updated source on page 2, not page 1. Mentioning which source you want to copy helps keep you and the user on track.

//#-editable-code
//#-copy-destination("Page1", id1)

//#-end-copy-destination
//#-end-editable-code

If you’re using a branching storyline (for example, you might explore variations on a sort or showcase different blending modes for merging images), you can place this destination code on each branch page.

More often, you’ll want to progressively modify code through a series of exercises. To carry the code further, add copy-source tags around the destination as in the following code, using the same id1 identifier, and refer to #-copy-destination("Page2", id1) for the next copy on Page 3 and so forth. Read this directive as this is the copy destination for the code tagged with id1 sourced from page 2.

Here’s what an edit-and-carry approach looks like for a second page, referring back to ("Page1", id1). In my imagination, this is the first time code has been copied and this markup sets up a user-editable progression that can be carried to the third page and beyond.

//#-copy-source(id1)
//#-editable-code
//#-copy-destination("Page1", id1)

//#-end-copy-destination
//#-end-editable-code
//#-end-copy-source

That’s pretty much all you need: proper tags, proper localized strings, and proper id/page references. If you’d like to try out a copy of my playground, you can grab a copy from here or email me for a copy if that doesn’t work.

Advent day 3, part 1

Are you playing along with Advent of Code? I got started a little late this year, so I’m doing a couple of days each day until I catch up.

The basis of Advent of Code isn’t so much the beauty of your code as it is the correctness. Because of this, a lot of my code is hideously ugly, with design choices best described as “questionable”. For example, at one point, I used flatMap.count on returned optionals instead of returning zeroes and ones and reducing them with +. I’m using Swift because that’s the language that’s currently dominant in my brain, although a lot of the memory manipulation would have been easier with straight C.

I wanted to share my solution for the first half of day 3. The challenge stipulates a squared spiral pattern of numbers in a grid and then asks you to calculate the distance from each number to the center. The approach I came up with for part I proved completely useless for the second half of day 3, where I had to start over from scratch. (Normally, you just modify the first code with an extra function and you go from part I to part II pretty easily.)

I took a road with part I that really didn’t fit the mindset of the challenge givers. For me, I was thinking geometrically, noticing that this was a degenerate case of a series of concentric circles. However instead of calculating the distance with a sin-cos solution, the concentric squares created a stepped triangle wave instead. Because of this, I built my solution to traverse the triangle wave and deduce the distance as the radius + the phase of the wave for any given number.

I thought I’d share my code for this because it’s pretty short and I think it’s pretty unusual for the problem domain.

for n in [1024, 12, 23, 312051] {
    for i in sequence(first: 1, next: { $0 + 2 }) {
        // Find least bounding square that contains number
        let boundingSize = i * i
        if boundingSize >= n {
            // Start of the outer edge sequence
            let firstValue = (i - 2) * (i - 2) + 1
            
            // Calculate distance to center
            let radius = (i - 1) / 2
            
            // The first number is always positioned at the
            // bottom right, one up from the bottom
            var current = radius - 1
            
            // The `direction` differential is the basis of
            // the triangle wave generator. It flips at the
            // minimum (-radius) and maximum (radius) offsets
            var direction = -1
            
            // One trip through the outer edge will be
            // sufficient to find the value
            for value in firstValue ... boundingSize {
                if value == n {
                    print("Result for \(n) is \(radius + abs(current))")
                    break
                }
                
                // Generate the next value in the triangle
                // wave pattern to determine the distance
                // from the center
                current += direction
                if abs(current) == radius { direction *= -1 }
            }
            break
        }
    }
}

Needless to say, my solution for part II had nothing to do with this wave approach. Instead, I actually constructed the 2D array, populated it with numbers and then used those as an addressing scheme to collect sums. Outside the addressing, it was basically applying a 3×3 sum filter in an address-driven convolution. Much longer, not pretty, but reasonably effective.

In the end, if I had done my “fill then look up locations” approach I used for part II for the first puzzle, it would have provided a much quicker solution although I don’t think it would have been as short or, in my opinion, nifty.

What approach did you end up using for day 3? And what made you go with that design?

Initializing Typed Arrays

Foundation’s URLQueryItem is just a stringly-typed key-value pair. You create one with a name and value:

public init(name: String, value: String?)

Since Swift supports literal initialization, you’d think you could use a dictionary to set up a [URLQueryItem] array, right? Well, yes and no.

You can’t just conform Array where Element == URLQueryItem to ExpressibleByDictionaryLiteral. Array extensions with constraints cannot have inheritance clauses. There are several ways around this limitation.

First (and best), you can just map an initializer across a dictionary literal:

let result = ["key1": "value1", "key2": "value2", "key3": "value3"]
    .map({ URLQueryItem(name: $0.key, value: $0.value) })

Second, you could make URLQueryItem itself dictionary initializable, but that starts to get ugly:

extension URLQueryItem: ExpressibleByDictionaryLiteral {
    public typealias Key = String
    public typealias Value = String
    public init(dictionaryLiteral elements: (String, String)...) {
        guard elements.count == 1
            else { fatalError("URLQueryItem requires single key-value pair") }
        self.init(name: elements.last!.0, value: elements.last!.1)
    }
}

let uq: URLQueryItem = ["key": "value"] // okay
let uqs: [URLQueryItem] = [["key1": "value1"], ["key2": "value2"], ["key3": "value3"]] // bleh

Third, you could use some kind of intermediate type to produce a URL query item array using Swift shortcuts. For example, you can set up a struct that builds the query item array and then pull from there:

struct URLQueryItems: ExpressibleByDictionaryLiteral {
    public typealias Key = String
    public typealias Value = String
    let items: [URLQueryItem]
    public init(dictionaryLiteral elements: (String, String)...) {
        items = elements.map({ URLQueryItem(name: $0.0, value: $0.1) })
    }
}

let uqis: URLQueryItems = ["key1": "value1", "key2": "value2", "key3": "value3"]
uqis.items

But again, it’s really not an improvement on using a mapped dictionary.

In the best of all worlds, which doesn’t exist, you’d be able to do something like this, but I don’t think there’s a way to accomplish this in modern Swift. Solution 2 is about as close as you get.

myRequest.queryItems = ["key1": "value1", "key2": "value2", "key3": "value3"]

Is there something I’m overlooking? If so, let me know. Drop a comment, mail, or tweet. Thanks.

Update:

and

Four Lessons from Circle Intersection

Yesterday, a fairly simple discussion of circle intersection came up: how do you subtract one circle from another to form a “cut out” Bezier path. This allows you to add an affordance or decoration to a circle, but add some space between the primary figure and the secondary bubble.

Exploring this question provided some interesting lessons that I thought I’d share in a quick post.

Embrace Core Graphics Types

When working with basic geometry, redirect your mathematics to Core Graphics. Bezier paths, points, rects, and other core geometric features use CGFloat, not Double. You minimize your pain by extending CGFloat as needed to address common geometric concerns such as exponentiation or mathematical constants rather than switching back and forth between Swift.Double and CGFloat:

/// Exponentiation operator
infix operator **: HighPrecedence

extension CGFloat {
    /// Returns base ^^ exp
    /// - parameter base: the base value
    /// - parameter exp: the exponentiation value
    public static func **(base: CGFloat, exp: CGFloat) -> CGFloat {
        return CGFloat(pow(Double(base), Double(exp)))
    }
    
    /// Tau
    public static var tau = CGFloat(Double.pi * 2.0)
}

Construct utility types

It helps to think about the kinds of types that will support your geometric challenge. For this example, I built two new types: a line segment (2 end points) and a circle (a center and a radius). Bringing these under the Core Graphics umbrella unified my representations with the tools they need to express their geometry:

/// 2-point representation of line segment
public struct Segment {
    public let (p1, p2): (CGPoint, CGPoint)
    var dx: CGFloat { return p2.x - p1.x }
    var dy: CGFloat { return p2.y - p1.y }
    public var length: CGFloat { 
        return sqrt(dx ** 2 + dy ** 2) 
    }
}

/// Center/Radius circle representation
public struct Circle {
    public let center: CGPoint
    public let radius: CGFloat
}

Being Core Graphic native enables you to leverage constructors using the appropriate types. For example, my circle can construct a path for drawing to a UIKit-compatible context:

/// Returns a Bezier path sweeping between two angles
public func path(from startAngle: CGFloat = 0, to endAngle: CGFloat = CGFloat.tau, 
    clockwise: Bool = true) -> UIBezierPath {
    return UIBezierPath(arcCenter: center, radius: radius,
                        startAngle: startAngle, endAngle: endAngle,
                        clockwise: clockwise)
}

This path method allows me to express each circle as a path, hiding the details of a UIBezierPath constructor. When I want to throw up a visual reference point, I just construct a circle at that point and fill it:

let p1 = Circle(center: segment.p1, radius: 2.5)
p1.path().fill()

Very handy.

Let the math be the math

When you’re working with standard algorithms, it helps to step back from your standard Swift key paths and use the terms of art you’re translating into code. For example, it can be convenient to break down some basic Swift into algorithm-specific terms:

let (x1, y1, r1) = (self.center.x, self.center.y, self.radius)
let (x2, y2, r2) = (other.center.x, other.center.y, other.radius)

It may not be “Swifty”, but doing so leads to easier inspection when comparing your implementation to the how-to reference in a book or paper.

Draw It

Playgrounds are great when it comes to testing drawing algorithms because you can use real data and get immediate results to see whether your assumptions and expectations are properly met.

In this example, the first two circles intersect, allowing the construction of the “chunked out” major circle and a condensed minor circle. The original circles are outlined and the two red points indicate the overlap points.

The second pair does not intersect, so it’s left simply as two outlines.

If you want to play around with this rough implementation, I left the code for this over at github. Feel free to expand or improve upon my approach, as it was very much an off-hand “here’s more or less how you can do this” exercise.

Challenge: Filtering associated value enumeration arrays

The Challenge

Courtesy of Mike Ash, here’s the challenge. You have an enumeration:

enum Enum {
    case foo(Int)
    case bar(String)
    case qux(Int)
}

And you have an array of them:

let items: [Enum] = [.foo(1), .bar("hi"), .foo(2)]

Return a filtered array containing only one case, for example foo. The difficulty lies in that Swift does not seem to offer a == or ~= operator that works on cases, ignoring associated values:

// does not work
let filtered = items.filter({ $0 == .foo })

So what do you do?

Attempt 1

Here’s my first attempt. Super ugly but it gets the job done:

let filtered = items.filter({ 
    switch $0 { case .foo: return true; default: return false } })

Evan Dekhayser prefers if-case:

let filtered = items.filter({ 
    if case .foo = $0 { return true }; return false })

And you can of course use guard as well:

let filteredy = items.filter({ 
    guard case .foo = $0 else { return false }; return true })

Attempt 2

Just as ugly but slightly shorter in terms of number of characters. But it does more work than #1:

let filtered = items.filter({ 
    for case .foo in [$0] { return true }; return false })

Again, yuck.

Attempt 3

I really hate this approach because you have to implement a separate property for each case. Double yuck:

extension Enum {
    var isFoo: Bool {
        switch self { case .foo: return true; default: return false }
    }
}
let filtered = items.filter({ $0.isFoo })

Attempt 4

This is gross because it requires a placeholder value for the rhs, even though that value is never used. And no, you can’t pass an underscore here:

extension Enum {
    static func ~= (lhs: Enum, rhs: Enum) -> Bool {
        let lhsCase = Array(Mirror(reflecting: lhs).children)
        let rhsCase = Array(Mirror(reflecting: rhs).children)
        return lhsCase[0].0 == rhsCase[0].0
    }
}
let filtered = items.filter({ $0 ~= .foo(0) })

Attempt 5

Then I got the idea into my head that you could use reflection. If you don’t supply a value to an enumeration case with an associated value, it returns a function along the lines of (T) -> Enum. Here is as far as I got before I realized the enumeration *name* was not preserved in its reflection:

import Foundation

extension Enum {
    var caseName: String {
        return "\(Array(Mirror(reflecting: self).children)[0].0!)"
    }
    
    static func ~= <T>(lhs: Enum, rhs: (T) -> Enum) -> Bool {
        let lhsCase = lhs.caseName
        let prefixString = "Mirror for (\(T.self)) -> "
        let typeOffset = prefixString.characters.count
        let typeString = "\(Mirror(reflecting: rhs).description)"
        let rhsCase = typeString.substring(from: typeString.index(typeString.startIndex, offsetBy: typeOffset))
        return true
    }
}

Yeah. Really bad, plus it doesn’t work.

Call for solutions

Since I didn’t really get very far with this, I’m throwing this out there as an open challenge. Can you come up with a parsimonious, readable, and less horrible (I was going to say “more elegant”, but c’mon) way to approach this? I suspect my first attempt may be the best one, which would make me sad.

A few interesting things about iOS Swift Playgrounds

Misc rambles:

Interesting: You no longer “print” in iOS Swift Playgrounds. Anything that can be presented using a playground QuickLook or a custom string representation is done so with the tap-to-view item at the right. There’s no “printing” per se, no console, while I suppose you can import Foundation and NSLog stuff, I’m not sure how reasonable a solution that is, especially on the go.

Because: This morning I ended up importing AVFoundation to let AVSpeechSynthesizer “speak” feedback to me. Not ideal, but short and easy to implement, and got the job done for some stuff that wasn’t rendering nicely the way I needed it to, in a complicated playground book that was using SceneKit not UIKit.

Rad discovery of the day: Command-R runs the playground without having to tap the screen. \o/ Press and hold Command key (on a physical Bluetooth keyboard, this doesn’t work on, for example, type2phone) to discover other shortcuts:

screen-shot-2016-11-11-at-3-13-29-pm

Sad discovery of the day: You cannot air drop playground books anymore, and Swift Playgrounds is being very very careful about allowing you access to any material you didn’t create or import yourself. There’s no Documents support for iTunes. At the suggestion of Jonathan Penn, I gave it a try after rebooting and now it works. You wouldn’t believe how much time I wasted trying to extract information to look up implementation details.

Thanks again to Jonathan P for pointing me to the command-key discovery feature!

Swift By Emoji: A considered approach

Not too long ago Iain Delaney pointed me to this graphic:

cwniukiukaaydtj

The graphic was designed by Steve Luscher and written about by Joey Devilla in this blog post on Global Nerdy. I thought it was brilliant and inspiring.

It wasn’t written in Swift and certainly wasn’t running in Swift. I decided to play around: I built a playground, assigning massive lists of emoji strings to emoji variables, and got these examples running properly using Swift syntax.

mapfilterreduce2

Rather than use a pile of poo, which assumes at each stage of reduction you’re combining poo with a new food, I went with Jaden Geller’s recommendation on Twitter. In the Swift version, the reduction starts with a sad face and becomes happy and satisfied.

I played around with other foods to see if it was worth expanding the samples but it was never quite as clean or elegant as the simple 4-item original:

mapfilterreduce1

Stepping away from the cow/potato/chicken/corn space, I wanted to see if there might be a better filter than isVegetarian. A child makes amusing (if not nutritious) food choices:

filter

And then I thought, well what about other Swift language essentials. So I mocked up the concept of naming items by whether they are mutating or non-mutating:

mutating

And repeating:

repeating

And sorted (although this one could probably use some better food choices):

sorted

Zipping was an obvious win as well:

zip

And map vs flatMap:

flatmap

Unfortunately, a soccer ball is not a valid character identifier so I couldn’t bitcast between a European football and an America one. Inconsistent Emoji character sets made me sad. Swift needs a standards-based operator and identifier makeover:

unsafebitcast

By the time I started playing with fatalError, I realized I was spending way too much time on this:

fatalerror

Do you have any favorite Swift functionality that lends itself to emojification? I’ve showed you mine. Now, show me yours.

Update: Phil Aaronson suggests using emoji functions too.

Ideally, examples should be able to compile and run in a Swift playground but I’m open to concepts that can be better explained with Emoji even when implementation is tricky.

Holy War: Enum Hash Values and Option Sets

I recently engaged in a conversation on the Swift Users list about converting a JSON array of string values into an enumeration set. I somewhat tongue in cheek suggested that these values be converted into an string-based enumeration, and then their hashValues be used to set-up flags.

I was, of course, immediately (and rightfully) challenged on whether a solution should hinge on the hashValue implementation detail — it shouldn’t. But the more I thought about this, I wondered whether it might be reasonable to eliminate potential errors by using the hash values to guide the option set creation.

Here’s what I mean. Consider this enumeration:

private enum LaundryFlags: String { 
    case lowWater, lowHeat, gentleCycle, tumbleDry }

You can use the enumeration to populate an option set, knowing each hashValue will not overlap, allowing the compiler to choose the implementation details without ever touching them yourself:

public static let lowWater = LaundryOptions(rawValue: 
    1 << LaundryFlags.lowWater.hashValue)

This approach allows you to build option sets from strings but not worry what the raw values are. Whatever the compiler picks will be consistent:

// String based initialization
public init(strings: [String]) {
    let set: LaundryOptions = strings
        .flatMap({ LaundryFlags(rawValue: $0) }) // to enumeration
        .map({ 1 << $0.hashValue }) // to Int, to flag
        .flatMap({ LaundryOptions(rawValue: $0) }) // to option set
        .reduce([]) { $0.union($1) } // joined
    _rawValue = set.rawValue
}

There are limits. You cannot use enumerations to represent compound convenience members like the following examples:

public static let energyStar: LaundryOptions = [.lowWater, .lowHeat]
public static let gentleStar: LaundryOptions = energyStar.union(gentleCycle)

On the other hand, you can adopt CustomStringConvertible pretty easily even though raw-value enumerations do not report their members and cannot be initialized from hash values. As the following code shows, it’s not a huge burden to generate a lazy member dictionary. You can boiler plate the implementation and copy/paste your case list into this array:

static var memberDict: Dictionary<Int, String> = 
    [lowWater, lowHeat, gentleCycle, tumbleDry]
    .reduce([:]) {
        var dict = $0
        dict[$1.hashValue] = "\($1)" 
        return dict
}

Reduce the dictionary with bit math from the option set:

public var description: String {
    let members = LaundryFlags.memberDict.reduce([]) {
        return (rawValue & 1 << $1.key) != 0
            ? $0 + [$1.value] : $0
    }
    return members.joined(separator: ", ")
}

So here’s the holy war question: given how simple and reliable this approach is, do I back off of my “never use implementation details” guidance for raw value enumerations and their hash values?

Full gist is here.