Archive for April, 2016

Converting loops

Just leaving this here.

for var i = 0, j = 1; i < 5; i += 1, j = 1 << i, print("values", i, j) {
    print("2^\(i) is \(j)")
}

Is basically:

for <variable declarations>; <end condition test>; <updates> {
    <body>
}

Update: So why did I pick this loop in the first place? I googled around for the ugliest most complicated examples I could that involved multiple variables and side effects. I want to show that there’s a simple mechanical conversion, even for the crazy.

And you can change this to this:

do {
    <variable declarations>
    while <end condition test> {
        <body>
        <updates>
    }
}

Like this:

do {
    var i = 0, j = 1
    while i < 5 {
        print("2^\(i) is \(j)")
        i += 1; j = 1 << i; print("values", i, j)
    }
}

Or this, if you’d like to keep the original bits all together, you can use defer. Note that any early loop termination will still trigger the defer block.

do {
    <variable declarations>
    while <end condition test> {
        defer { <updates> }
        <body>
    }
}

Like this:

do {
    var i = 0, j = 1
    while i < 5 {
        defer { i += 1; j = 1 << i; print("values", i, j) }
        print("2^\(i) is \(j)")
    }
 }

And yes, you can still use break and continue

do {
    // Count to 49 by 2s
    var i = 0, j = 100
    while true {
        defer { i += 1; j -= 1 }
        if i % 2 == 0 { continue }
        if i >= j { break }
        print(i, terminator:" ")
    }
    print("")
}

And labels

 do {
    // count to 23 by 2s
    var i = 0, j = 100
    outer: while true {
        inner: while i < j {
            i += 1; j -= 1
            if i % 2 == 0 { continue inner } // same as continue
            print(i, terminator: " ")
            if i == 23 { break outer }
        }
    }
    print("")
}

Unbounded ranges

Swift ranges in their current state include two variations: n...m, a closed range that includes both n and m, and n..<m, a half-open range that includes n but stops short of m. I’m working on proposals to introduce a striding(by:) method and enhance range operators for Swift 3.

Last night I was chatting with Nate Cook about the possibility of unbounded ranges, in other words, a range that wasn’t limited on one side or another but that went off towards infinity. You can think of these as a kind of “range ray”, pointing out either up or down the number line.

For example, 5... is a an unbounded range including all numbers greater than or equal to 5, and 5<.. would be the equivalent open version that didn’t include 5.

Nate recently wrote up a bunch of operators to support working with unbounded ranges but it turns out you don’t really need these if you use some built in number properties to create “unbounded” (the quotes are deliberate) ranges. Let me step back and set things up before jumping into the solution.

The main reason you’d ever want to use unbounded ranges is for pattern matching. You can use the ~= operator, switch statements, if case and guard case to test whether a range contains a value.

Now you might just now be thinking: why use “5<.. ~= x” when you can just say “if x >= 5“? The latter is shorter, clearer, and far more obvious. The answer is this case comes down to those pattern matching scenarios, which primarily consist of switch statements and a few oddball if case/guard case uses.

The following switch statement provides a case for x >= 5, but it does so by binding a new variable and then building in a where clause.

switch i {
case let x where x >= 5:
    print(i, "is >= 5")
default:
    print("nope")
}

Surely there’s a better way to frame this. And there is. Nearly every number type offers either .min and .max static properties or .infinity, or in the case of CGFloat, both. (Use a minus sign to get -.infinity if you need that.)

If you plug that back into the switch statement, you end up with a much more satisfying case:

// Note: a ... b translates to a ..< b + 1 
// so a ... .max fails, which is why it is ..< .max here 
// If you want, you can add an Int.max case *or*
// you can use 5 ... .max as ClosedInterval
switch i {
case 5 ..< .max: 
    print(i, "is >= 5")
default:
    print("nope")
}

So you don’t need special operators to create open ranges suitable for pattern matching. You can work with the number constants that already exist:

  • Integers: i ..< .max and .min ... i
  • Doubles: -.infinity ... f and f ..< .infinity

Once the range operator vocabulary expands, you’ll be able to reference  i <.< .max and f <.< .infinity as well, filling in the current gaps in the system.

The canonical guide to range operators

Closed range: ... aka the stony path

Half open range #1: ..< aka the manic upside down duck

Half open range #2: <.. aka the upside down chick

Fully open range: <.< aka the disapproving squint

Alternatives

If treating the < portion visually, like ] and [:

Half open range alternative: >.. another manic upside down duck

Fully open range alternative: >.< aka the d’oh operator

Folding generic argument lists

A generic argument list refers to the bit in angle brackets that follow a method name and precede the parenthesized argument list. These clauses specify generic type arguments and the constraints that limit their application. Swift generic specification can grow very big very quickly. And they are a pain to wrap.

The Swift Standard Library group has come up with a creative way to handle this situation, which is about as aesthetically pleasing as Soviet Brutalist Architecture:

public init<
 S : Sequence where S.Iterator.Element == Iterator.Element
>(_ elements: S) {
  self.init()
  append(contentsOf: elements)
}

The line that really kills it for me is the one with the closing angle bracket, the argument list, and the opening brace all on the same line.

As the generic argument and parameter lists grow longer, Apple’s folding style becomes less standardized. This example puts where on its own line (not a bad thing) but breaks out the function parameter list into three lines

internal func _transcodeSomeUTF16AsUTF8<
  Input : Collection
  where
  Input.Iterator.Element == UInt16>(
  input: Input, _ startIndex: Input.Index
) -> (Input.Index, _StringCore._UTF8Chunk) {
  typealias _UTF8Chunk = _StringCore._UTF8Chunk
  ...
}

The example that follows co-aligns where but confuses me with its long parameter list, which is broken into lines of three apparently unrelated undefaulted parameters and a following line with a defaulted parameter.

static func fromCodeUnits<
  Input : Collection, // Sequence?
  Encoding : UnicodeCodec
  where Input.Iterator.Element == Encoding.CodeUnit
>(
  input: Input, encoding: Encoding.Type, repairIllFormedSequences: Bool,
  minimumCapacity: Int = 0
) -> (_StringBuffer?, hadError: Bool) {

Swift allows the angle bracket to be spaced away from a function name even though that’s an atypical use and I am, frankly, not a fan. For example, the following example compiles and works as you’d expect

// This will compile
protocol MyProtocol {}

func myFunction
    <T: MyProtocol>
    (x: T)
{
    ... 
}

And you can further break down the generic argument clause onto new lines. Xcode doesn’t really like this so you have to hand-indent the components:

func myFunction
    <
        T: MyProtocol
    >
    (x: T)
{
    print(x)
}

So if you really wanted to, you could build something more like this:

internal func _transcodeSomeUTF16AsUTF8
    < Input : Collection
      where
      Input.Iterator.Element == UInt16
    >( input: Input, _ startIndex: Input.Index 
    ) -> (Input.Index, _StringCore._UTF8Chunk) {
    typealias _UTF8Chunk = _StringCore._UTF8Chunk
    ...
}

Whether you’d want to is another discussion. This refold certainly emphasizes the generics,  parameters, and return type sections.

Moving back a little into reality world, here’s a deployed example from the Github Focus repo. In this example, extra indentation helps move the where clauses closer to the starting bracket of the argument list.

public func • <Left : LensType, Right : LensType where
	Left.Target == Right.Source,
	Left.AltTarget == Right.AltSource>
	(l : Left, r : Right) -> Lens<Left.Source, Left.AltSource, Right.Target, Right.AltTarget> {
		return l.compose(r)
}

Here’s one from TJ:

CfYA4SKVIAAAe7V

While I like the intent, I really don’t like the abnormal indentation. So I pulled up an old example from my massive “notes and tests” playground to share. This one uses multiple generic arguments and constraints but fairly standard indentation. Unlike all the preceding examples, my where keyword and constraints are spaced in further than the type arguments.

func ====<
    Seq1: SequenceType,
    Seq2: SequenceType
        where
        Seq1.Generator.Element == Seq2.Generator.Element,
        Seq1.Generator.Element: Equatable
    >(seq1: Seq1, seq2: Seq2) -> Bool 
{
    var gen2 = seq2.generate()
    return !seq1
        .lazy
        .contains({ $0 != gen2.next() })
        && gen2.next() == nil
}

In terms of readability I think it’s pretty clear where each part of the generic story is expressed. Using the same approach, here is the refolded fromCodeUnits example:

static func fromCodeUnits<
    Input : Collection, // Sequence?
    Encoding : UnicodeCodec
        where
        Input.Iterator.Element == Encoding.CodeUnit
    >(
        input: Input,
        encoding: Encoding.Type,
        repairIllFormedSequences: Bool,
        minimumCapacity: Int = 0
    ) -> (_StringBuffer?, hadError: Bool)
{
    ...
}

Screen Shot 2016-04-06 at 11.51.30 AM

What do you think? Are there any specific rules you follow? And do you have any folding examples to share? Let me know.

Multicellular Swift: evolution in action

Note: If any more acceptances or reviews show up today or tomorrow, I’ll be updating this post rather than creating a new one.

Accepted Proposals

SE-0053 Remove explicit use of let from Function Parameters got rid of a single case that prevented SE-0001 from being implemented without exceptions. It’s a bookkeeping kind of proposal but one that simplifies and cleans up Swift.

SE-0016 Adding initializers to Int and UInt to convert from UnsafePointer and UnsafeMutablePointer means you won’t have to write all your pointer arithmetic in C: “Just as users can create Unsafe[Mutable]Pointers from Ints and UInts, they should be able to create Ints and UInts from Unsafe[Mutable]Pointers. This will allow users to call C functions with intptr_t and uintptr_t parameters, and will allow users to perform more advanced pointer arithmetic than is allowed by UnsafePointers.”

SE-0054 Abolish ImplicitlyUnwrappedOptional (IUO) type was accepted pending user experience, or as I like to call it, “Swift try before Swift buy“. The idea is that IUO moves from the type system to declaration attribute. “The appearance of ! at the end of a property or variable declaration’s type no longer indicates that the declaration has IUO type; rather, it indicates that (1) the declaration has optional type, and (2) the declaration has an attribute indicating that its value may be implicitly forced.”

SE-0055: Make unsafe pointer nullability explicit using Optional. “Today, UnsafePointer and friends suffer from a problem inherited from C: every pointer value could potentially be null, and code that works with pointers may or may not expect this. Failing to take the null pointer case into account can lead to assertion failures or crashes. This proposal makes UnsafePointer<Int> represent a non-nullable pointer, and UnsafePointer<Int>? a nullable pointer. This also allows us to preserve information about pointer nullability available in header files for imported C and Objective-C APIs.”

In Review

Dear Erica: Can I build a throwing operator

Another question from Ethan J. He writes, “If I wanted to implement an operator similar to ?? but one that throws when the left side is nil how would that look?” Basically he wants  the opposite of a coalescing operator that instead of offering a fallback value will raise an error when the LHS is nil.

I’m interpreting the brief here as “create a throwing version of nil coalescing specifically for use where the original code author has provided optional return values but has not updated code to work with the error handling system.”

Here’s what I came up with. !! seems a nice natural counterpart to ??.

struct Error: ErrorType { let reason: String }
infix operator !! {}

// Simple LHS optional (Thanks, Pyry Jahkola)
// Using @autoclosure is a good idea for strings with expensive interpolation (Thanks, Mike Ash)
func !!(lhs: T?, @autoclosure reason: () -> String) throws -> T {
    switch lhs {
    case .Some(let value): return value
    default: throw Error(reason: reason())
    }
}

Here are a couple of examples of successful and non-successful calls that mimic Ethan’s use case, which was to convert failable but non-throwing calls into throwing ones.

do {
    let z = try Int("x") !! "Invalid integer initializer"
    print("Value", z)
} catch { print(error) }

do {
    let z = try Int("42") !! "Invalid integer initializer"
    print("Value", z)
} catch { print(error) }

I went with string-based errors for simplicity, allowing the operator implementation to construct and throw errors using that information.

Pyry Jahkola offers an alternative approach. Instead of building a new operator, he suggests building an evaluatable RHS that could be used with nil coalescing as is:

func raise<T>(error: ErrorType) throws -> T { throw error }
func raise<T>(@autoclosure reason: () -> String) throws -> T {
    throw Error(reason: reason())
}

With this, you could use an approach similar to using && as an if-true condition:

do {
    let z = try Int("42") ?? raise("Invalid integer initializer")
    print("Value", z)
} catch { print(error) }

Using a separate function would also enable you to incorporate debug literals to capture the context of the nil result.

Notes:

  • Mike Ash mentions that he wrote an extension on Optional, something like x.orThrow(e) to do more or less the same thing.
  • Perhaps I should call !! a “nil-throwing operator”? (Thanks,  Michael M. Mayer).
  • As for the standard library, while I’d like to see a standard fallback error type, my idea of introducing a basic pre-built default error was not warmly greeted in Swift Evolution discussion threads.

Try hard with a vengeance

Ethan J. hopped into the swift-lang irc tonight asking why the following was possible and was there any difference between the two forms:

do {
    var x = try throwingFunction()
    try x = throwingFunction()
} catch {}

The best I can come up with is that try is applied to expressions not function calls, and the assignment expression is tried as a single unit.

Screen Shot 2016-04-04 at 6.10.28 PM

You cannot, however, declare and try on the same side of the assignment

// let try x = throwingFunction() // nope
// try let x = throwingFunction() // also nope

Got a better answer? Do let me know!

Update: Jon A asks: “But isn’t x = y a statement and not an expression?” As Mike Ash pointed out in our chat, assignments are still expressions. “It’s just that their type and value are not what you might expect” The following is legal Swift:

 var a = 1
 var b = 2
 var c = a = b

And c‘s type is () and its value is also (). Mike adds that this might be the only place in Swift where a type and a value of that type are written identically.

Screen Shot 2016-04-04 at 7.36.48 PM

If you want to have more fun, you can put the try just about anywhere in the following expression. Mike explains, “try doesn’t actually do anything. It’s just that the compiler forces you to put it on any expression which can throw. [It acts] as a marker.”

Screen Shot 2016-04-04 at 7.57.04 PM

And then there‘s:

Screen Shot 2016-04-04 at 8.41.41 PM