Archive for March, 2016

The great evil of co-linear closure declarations

I am personally opposed to this:

try fopen(moduleMapPath, mode: .Write) { fp in
    try fputs("\n", fp) 
}

Why put the declaration line in a complete different place from the rest of the code? Move it down and let it annotate the use that follows:

try fopen(moduleMapPath, mode: .Write) { 
    fp in
    try fputs("\n", fp) 
}

Today’s complaint is brought to you by the letters “i” and “n” and the return type Void.

Xcode Upgrades: Lessons learned

Yesterday was remarkably instructive when it comes to how badly App Store can completely mess up a download: particularly for a popular app like Xcode that’s being requested by gazoodles of people at once.

CeGpK4VXEAA4jja

My download got stuck over and over. I had to clear out my app store caches, restart my app store daemons, and reboot my computer several times.

I ended up with a partial install that thought it was done, that installed all the “extra” components on launch, and then turned out to be a 7.2.1 install that was convinced it was 7.3. It was not.

I even cleaned up the whole install process, tossed my mangled 7.2.1, restored a copy from Time Machine (not a quick process), and tried to update again from the store.

I couldn’t use Xcode during this time to get any work done.

Screen Shot 2016-03-21 at 5.13.19 PM

I spent roughly 8 hours all told downloading, installing, and updating Xcode, much of which could have been bypassed by following two simple rules:

  1. Never update Xcode from the Mac App Store
  2. Wait until Apple posts the upload on developer.apple.com/downloads and  then update from there.

When Apple’s servers are overwhelmed they begin delivering artisanal teaspoons of hand-curated data via authentically indigenous pack animals to your computer. Apple has taken its passion for the slow data delivery movement beyond its products and introduced it into its upgrade practices.

Screen Shot 2016-03-22 at 9.43.41 AM

As part of their continuing mission to leave the world a better place, Apple delivers beautiful products using the most impact-free transmission. This commitment assures that developers are forced to stop work and smell the roses, as Apple promotes appreciation for our beautiful planet and life outside of the IDE window.

Under such circumstances, you’ll always be better off  downloading the bossy full-figured 5GB dmg than upgrading a model-thin Chanel-wearing 2.6GB differential, especially when servers are mocking you with NananaNAN completion estimates.

This is why you should always wait for a DMG. No matter how long it takes to appear on the developer site. No matter how slow the download ends up being. The advantages of downloading a DMG are numerous:

  1. It does not block you from  using Xcode during the entire day or however long it takes for your download to complete.
  2. It does not hang App Store or produce a situation where it insists on taking over the download (“Apple’s App Store download servers have a cheerful and sunny disposition. It is their pleasure to download for you using the gentle rhythms of tectonic flow and their satisfaction to keep you from getting any work accomplished, with a knowledge of a job well done.”)
  3. You can see exactly how much data has downloaded in terms of real progress and not imaginary hidden-temporary-file weird pkgs that takes over your /Applications folder and refuse to surrender that spot once active.
  4. Simple downloads are better for your resting heart rate, your blood pressure, and world peace.

Update: Final lesson. If you have downloaded the dmg directly from Apple and not from a third party source, you can run the following to skip the verification checks:

sudo xattr -d com.apple.quarantine /Applications/Xcode.app

Proceed at your own risk. Make sure you know what you’re doing and accept those risks.

Sign of the times

What would you do to improve the following?

func sign<T: SignedNumberType>(value: T) -> Int {
   return value == (0 as T) 
       ? 0 : (value > 0 ? 1 : -1)
}

or if you like it typed:

func sign<T: SignedNumberType>(value: T) -> T {
    return (value == (0 as T) 
        ? 0 : (value > 0 ? 1 : -1)) as T
}

Here’s what I call the Groffian Lapse In Judgement:

extension Bool: RawRepresentable {
  public typealias RawValue = Int
  public var rawValue: Int {return self ? 1 : 0}
  public init?(rawValue: Int) { self = rawValue == 1 }
}

func signbadTheSailor<
        T: protocol<SignedNumberType, IntegerLiteralConvertible>
        where T.IntegerLiteralType: SignedIntegerType
    > (value: T) -> T {
    let theSign = (value > 0).rawValue - (value < 0).rawValue
    let result: T.IntegerLiteralType = numericCast(theSign)
    return T(integerLiteral: result)
}

Thanks.

Watching paint dry

So I’m waiting for Xcode to eventually download because I actually need to use it in my real life. Everything has come to a screaming halt because it’s dinner time and because of this:

Screen Shot 2016-03-21 at 5.13.19 PM

and this:

Screen Shot 2016-03-21 at 4.54.54 PM

So instead, I have some notes sitting around while I make dinner. I can’t guarantee any of them make any sense whatsoever (since I can’t open Xcode to test) but I thought I’d just throw them out there and see if they connect with anyone out there in the land of electrons beyond my screen. It may be useful. It may be crap.

Looping through a sequence of integers:

for index in 0..<n {...}

Looping with a where clause:

for index in 0..<n where n % 2 == 0 { }

Looping with map:

for index in (1..<n).map({ $0 * 10 }){ } // 10 to n-ty
for index in (1..<n).map({ pow(2.0, Double($0) }){ } // 2^idx

Theoretically you could adjust “stride” to take a function but you really don’t want to.  If you’re using value(n+1) = f(value(n)) it’s not a stride. It’s something something non-stride. I call it stride here because whoever I was talking with was all “couldn’t stride take a closure”? and I was all “yeah, sure”:

func stride(from value: Int, to cutoff: Int, by f: (Int) -> Int) -> AnySequence<Int>  {
    var current = value
    return AnySequence {
        return anyGenerator {
            guard current <= cutoff else {return nil}
            defer {current = f(current)}
            return current
        }
    }
}

The closures aren’t particularly self-documenting or readable. And don’t try to produce side-effects in the by closure. That’s just wrong.

for i in stride(from: 1, to: 10, by: {$0 + 1}) // ++
for i in stride(from: 1, to: 1_000_000, by: {$0 << 1}) // shift
for i in stride(from: 1, to: 200, by: {$0 * 2 + 1}) // 2x + 1
Some traditionalists want to directly affect an index, not just supply the RHS of an assignment. The second you introduce inout, the clarity and readability plummet from an already not-very-great situation.
func stride(from value: Int, to cutoff: Int, by f: (inout Int) -> Void) -> AnySequence<Int>  {
    var current = value
    return AnySequence {
        return anyGenerator {
            guard current <= cutoff else {return nil}
            defer {f(&current)}
            return current
        }
    }
}

for i in stride(from: 1, to: 10, by: { (inout idx: Int) in idx += 1 }) {}
for i in stride(from: 1, to: 1_000_000, by: { (inout idx: Int) in idx = idx << 1 }) {} // shift
for i in stride(from: 1, to: 200, by: { (inout idx: Int) in idx = idx * 2 + 1 }) {} // 2x + 1

 

No floating point stuff here because floating point is broken. If you really need it, well you could do worse than this for stuff like iterating by M_PI/30 at a time around a circle or looping from 0.0 to 1.0 by 0.1.

func stride(from value: Double, to cutoff: Double, byOffset offset: Double) -> AnySequence<Double>  {
    var count = 0 // Int
    return AnySequence {
        return anyGenerator {
            let current = value + Double(count) * offset
            guard current <= cutoff else {return nil}
            defer {count += 1}
            return current
        }
    }
}

Swift 2.2 released. Xcode updated to 7.3

Announced at swift.org:

We are very pleased to announce the release of Swift 2.2! This is first official release of Swift since it was open-sourced on December 3, 2015. Notably, the release includes contributions from 212 non-Apple contributors — changes that span from simple bug fixes to enhancements and alterations to the core language and Swift Standard Library.

Updates include those discussed in my earlier 2.2 Beta post.

A few notes:

  • SE-0001 currently has 3 exceptions. All those exceptions will likely go away by Swift 3.
  • SE-0015 Tuple comparison operators is a lovely little tweak by Lily Ballard.
  • SE-0011 fixes an issue with confusing keywords. Protocols now have associatedtypes to express placeholder types. You continue to implement these (and other type aliases assignments) with typealias.
  • SE-0021 allows you to disambiguate overloaded functions. You can now name functions included argument names. It’s brother proposal, SE-0022 adds #selector that builds selectors from method references.
  • SE-0020 is the first new build configuration (hopefully there will be more) that enables you to specialize your code based on Swift language releases.

If you’d like to see what’s still in the works, hop by Swift Evolution on github. The main ReadMe page has a list of what you can expect in Swift 3.0 and the review schedule lets you know which proposals will be up for public review and when.

Should I be using a generator or not?

Here’s my situation. I have an endless sequence that generates integers from min to max and back. So I initially figured, “let me just make a generator”. (I’m not saying this is a good generator. I just want to know if I should be using a generator here.)

public struct UpAndDownIntGenerator: GeneratorType {
    public typealias Element = Int
    let (magnitude, period): (Int, Int)
    let minValue: Int
    var currentOffset: Int = 0

    public init(minValue: Int = 0, maxValue: Int) {
        assert(minValue < maxValue, 
            "minValue must be less than maxValue") 
        self.minValue = minValue 
        magnitude = maxValue - minValue 
        period = magnitude * 2 
    }

    public mutating func next() -> Int? {
        let value = currentOffset % period
        let adjustedValue = value % magnitude
        let isAscending = value < magnitude
        defer { currentOffset += 1 }
        return minValue + (isAscending 
            ? adjustedValue 
            : magnitude - adjustedValue)
    }
}

But this generator is never going to terminate and I know it will always return a non-nil value. So I added this:

    // This is not going to be fed into a sequence
    // so fetch the next value and test for nil
    public mutating func fetchNextValue() -> Element {
        guard let value = next() else {
            fatalError("unable to generate next value")
        }
        return value
    }

And then I was all: So why bother being a generator with the extra overhead? Why am I creating something that has the hallmarks of a generator but isn’t suitable for use in a sequence (for example, mapping over an infinite sequence or filtering, or just figuring how to grab one value at a time). So then I wrote this:

public struct UpAndDownProducer {
    let (magnitude, period): (Int, Int)
    let minValue: Int
    var currentOffset: Int = 0

    public init(minValue: Int = 0, maxValue: Int) {
        assert(minValue < maxValue, 
            "minValue must be less than maxValue") 
        self.minValue = minValue 
        magnitude = maxValue - minValue 
        period = magnitude * 2 
    }

    public mutating func next() -> Int {
        let value = currentOffset % period
        let adjustedValue = value % magnitude
        let isAscending = value < magnitude
        defer { currentOffset += 1 }
        return minValue + (isAscending 
            ? adjustedValue 
            : magnitude - adjustedValue)
    } 
}

So what should I actually be doing here? Advice greatly appreciated.

p.s. The following would be a much simpler approach:

public struct UpAndDownProducer {
    let minValue, maxValue: Int
    var currentValue: Int
    var direction = -1
    
    public init(minValue: Int = 0, maxValue: Int) {
        assert(minValue != maxValue,
            "No point going up and down between two equal values")

       // Since it starts at minValue, it's
       // going to flip immediately.
       if maxValue < minValue { direction = 1 }
       currentValue = minValue 
       (self.minValue, self.maxValue) = (minValue, maxValue) 
    } 

    public mutating func next() -> Int {
        defer {
            if currentValue == minValue || currentValue == maxValue {
                direction *= -1
            }
            currentValue += direction
        }
        return currentValue
    }
}

p.p.s. Davide De Franceschi suggests something along the following lines:

protocol EndlessGeneratorType: GeneratorType {}
extension EndlessGeneratorType {
    public mutating func someNext() -> Element {
        guard let element = next() else { 
            fatalError("EndlessGeneratorType must always have a next() element") 
        }
        return element
    }
}

he adds:

 

Ask Erica: Why can’t I initialize my UInt?

CPow asks: “Why does this give an error? This makes no sense. I smell a radar…?”

Screen Shot 2016-03-17 at 8.00.26 AM

Answer: To the best of my understanding, the compiler sees that literal as an integer and is trying to use it with a UInt initializer. If you explicitly make sure the compiler understands that the literal is a UInt and not an Int, the problem disappears.

Screen Shot 2016-03-17 at 8.05.55 AM

(As Joe Groff points out, you obviously don’t need the UInt() in the “c” example, but I was trying to build off CPow’s question.)

Got a better explanation for CPow? Please let me know!

Behind the scenes: Swift core team design discussion 3/15

In the spirit of transparency, the Swift core team has posted its notes about upcoming proposals. These notes help guide the modification of existing proposal before they’re submitted to the community for an open review and give greater insight into the team’s views.

Apple’s Alex Martini writes, “These are informal comments, intended to guide the proposals in directions that draw constructive feedback. You are welcome to ignore the feedback, agree with it, or disagree with it.  As always, the formal decision doesn’t happen until after the review period ends.”

For example, in the notes about SE-0047, which changes the default behavior of Swift methods and functions to warn on unused results, you’ll note how the team considered whether the override attribute should apply to the return type.

They wrote, “We like how putting the @discardable on the type because of how it reads, but it’s not on the type.”) In the active proposal, the modifier is now  @discardableResult and it modifies the function or method. “It’s actually more semantically part of the function. You don’t have a “discardable integer”, you have a function whose result is discardable.”

Contrast that with SE-0049, which moves @noescape and @autoclosure to decorate types. “In short, @noescape and @autoclosure are attributes on the parameter. We got away with it before, but now that we’re requiring you to manually uncurry, you can’t write things that you used to be able to write. None of this makes sense; we should only accept these attributes in the type position.”

Some interesting (short) comments as well on SE-0042 (Flattening Method types), SE-0043 (Variables in Case Labels), and SE-0048 (Generic Typealiases).

Like my posts? Consider buying a book or two. Thanks!

About those two withdrawn proposals

If you hunt through the proposals folder on Swift Evolution, you’ll see that both SE-0050 and SE-0051 are “withdrawn by submitter”. A few people have asked me about this so I thought I’d throw up a post.

SE-0050’s withdrawal was actually an accident (I had been discussing SE-0051 and the two of them had started as a single proposal that was split in two.)

That said, Dave Abrahams is already working on fixing the SE-0050 problem as part of his work on indexing models. So long as the problem gets fixed, I’m happy. As I point out in the proposal, floating point numbers really shouldn’t conform to Strideable in its current incarnation or be genericized with integer types.

As for SE-0051, I felt that while the issues I brought up were valid, that there was a deeper design issue found in ranges, intervals, strides, etc that should probably be addressed post Swift 3. (“I don’t want to waste everyone’s time bailing water instead of designing a better hull.”)

If you’re interested, the three renamed functions in SE-0051 correspond to natural endpoints you’d encounter in loops, specifically “while less than”, “while less than or equal to”, and “until greater than or equal to”. There are examples in the proposal of the three conditions, and suggested renaming to better reflect those conditions.