Access Control Modifiers Proposal Thoughts

The big thread these days on swift-evolution is regarding access control modifiers. Swift supports a fairly limited set today, namely:

  • public: visible outside of the module
  • internal: visible within the module
  • private: visible within the file

There is a proposal, SE-0025: Scoped Access Level, that wants to add another layer to the mix: lexical scoping (I’ll use local in the example for it).

struct Outer {
    local let scopeVisible: Int
    private let fileVisible: Int
    func f() {
        /* scopeVisible is accessible here */
        /* fileVisible is accessible here */
    }
}

let o = Outer()
/* o.scopeVisible is not accessible here */
/* o.fileVisible is accessible here */

Today, in Swift, there is no way to provide this type of scoping mechanism within the same file.

My argument is that this proposal should be rejected, the Core Team thinks otherwise:

To summarize the place we’d like to end up:

  • “public” -> symbol visible outside the current module.
  • “internal” -> symbol visible within the current module.
  • unknown -> symbol visible within the current file.
  • “private” -> symbol visible within the current declaration (class, extension, etc).

The problem, as I see it, is that this is simply a one-off fix for one of the limitations for access modifiers today. There are other, arguably reasonable, asks for access control modifiers as well:

  • visibility to only extensions declared in the same file
  • visibility to only extensions
  • visibility to subclasses
  • visibility to specific functions or types (e.g. C++’s friend)

We could get even more fine grained as well:

  • visibility to only a specific set of modules
  • visibility within a specific submodule

I don’t think that these are all necessarily bad, in fact, some can be quite helpful. However, instead of just accepting this proposal and adding this specific change, I’d rather see the entire access modifier system to be revisited because this doesn’t really fix much, it just moves the problem.

The example used is this (where local means lexical scope):

class A {
   local var counter = 0

   // API that hides the internal state
   func incrementCount() { ++counter }

   // hidden API, not visible outside of this lexical scope
   local func advanceCount(dx: Int) { counter += dx }

   // incrementTwice() is not visible here
}

extension A {
   // counter is not visible here
   // advanceCount() is not visible here

   // may be useful only to implement some other methods of the extension
   // hidden from anywhere else, so incrementTwice() doesn’t show up in 
   // code completion outside of this extension
   local func incrementTwice() {
      incrementCount()
      incrementCount()
   }
}

Ok, so this addresses the problem that counter is not meant to be visible outside of type A. Maybe it was unintentionally being leaked. However, if counter is required to be used within one of the extensions, say a reset() function, then counter needs to be promoted to the file-based one. However, by doing so, we are again leaking counter to be more visible than it is supposed to be. So what was really the point?

At the end, if the current access modifiers are not sufficient because they are “too leaky”, then this proposal doesn’t fix the root problem. If the root problem is really sufficient enough, then I would think all of the modifiers should be revisited to provide the fine-grained access control system that is really being asked for.

Of course, I’m also just fine with the three we have and not trying to add all of the complexity required.

If you have thoughts on it, be sure to contribute here: http://thread.gmane.org/gmane.comp.lang.swift.evolution/12183/focus=12219

Access Control Modifiers Proposal Thoughts

Tooling Around – Testing in Swift

For those that don’t know, a few of us are working on a set of tools for building for Swift. As part of that work, I’ve been thinking about how some unit tests could be done in a much simpler way. D does something interesting for unit tests; it allows you to define them inline and have them runnable at build time. Pretty cool, though D’s implementation is a bit limited.

class Sum
{
    int add(int x, int y) { return x + y; }

    unittest
    {
        Sum sum = new Sum;
        assert(sum.add(3,4) == 7);
        assert(sum.add(-2,0) == -2);
    }
}

If we had the ability to create custom attributes in Swift (ok… this feature really requires custom attributes and compiler plug-ins), I was thinking that I could build something like this:

class Sum {
    func add(x: Int, _ y: Int) -> Int { return x + y }
}

@test("Sum", "add(_:_)", "checkin") {
    let sum = Sum()
    assert(sum.add(4, 5) == 9, "Math is hard!")
    assert(sum.add(-3, 3) == 0)
}

The intent is that this provides us with more functionality than what D offers, namely the ability to filter test cases by a number of factors including type, function names, test type (e.g. checkin), or any other text-based qualifier you want. Also, since it was an attribute, we could easily strip out these code paths if a flag, say -enable-testing, wasn’t used.

So, to run all of the checkin tests, you’d do something like this (assume we had some tool run-tests that is magical for now):

$ run-tests -match "checkin"

This would let us find all of the @test items with checkin as part of the metadata and run them.

Ok… that’s great, but Swift doesn’t allow us to create these attributes… so all hope is lost, right?

Nope, we can hack around to get what we want. =)

Instead, let’s do this:

class Sum {
    func add(x: Int, _ y: Int) -> Int { return x + y }
}

func __test_sum_add_checkin() throws {
    let sum = Sum()
    assert(sum.add(4, 5) == 10, "Math is hard!")
    assert(sum.add(-3, 3) == 0)
}

The idea is fairly simple:

  1. Build a static library of your module that you wish to test; make sure the -enable-testing flag is set. 2. For each Swift file with methods following our convention (top-level functions that start with __test_), create an executable that calls that function. 3. Run the executable.

Boom! Integrated unit tests.

Digging In

I’m using our build tool, but you can probably do something similar with Swift’s Package Manager.

Here’s the contents of my build file:

(package
  :name "IntegratedUnitTests"

  :tasks {
    :build {
      :tool "atllbuild"
      :sources ["Sum.swift"]
      :name "math"
      :output-type "static-library"
      :publish-product true
      :compile-options ["-enable-testing"]
    }

    :test {
      :dependencies ["generate-test-file"]
      :tool "atllbuild"
      :sources ["sum_test.swift"]
      :name "sum_test"
      :output-type "executable"
      :publish-product true
      :link-with ["math.a"]
    }

    :generate-test-file {
      :dependencies ["build"]
      :tool "shell"
      :script "echo '@testable import math' > sum_test.swift && xcrun -sdk macosx swiftc -print-ast Sum.swift | grep __test | sed 's/internal func/try/g' | sed 's/throws//g' >> sum_test.swift"
    }

    :run {
      :dependencies ["test"]
      :tool "shell"
      :script "./bin/sum_test"
    }
  }
)

The build task is responsible for creating the math.a static library. The test task is responsible for creating the test executable. The generate-test-file task actually does creates the source code for the test executable. It does the following:

  1. Creates a new file named sum_test.swift 2. Appends @testable import math to it 3. Examines the AST for Sum.swift and adds the calls for our test methods.

The final file looks like this:

@testable import math
try __test_sum_add_checkin() 

And when you run it:

assertion failed: Math is hard!: file Sum.swift, line 7

Yay! Inlined test code.

This is just a preview. I plan on flushing this out some more, but I thought it was interesting enough to post about. =)

Tooling Around – Testing in Swift

Sad State of Enums

Enums… those lovely little beasts of many uses. I really do like associated enums. Well, at least, I really like the idea of associated enums.

The problem: they really suck to work with.

Take for example you simply want to validate that an enum you got back is a specific enum case.

enum Simple {
    case SoEasy
    case Peasy
}

func simple() -> Simple { return .SoEasy }

func testSimple() {
    assertme(simple() == .SoEasy)
}

This is a cake walk with normal enums. But…

enum DoYou {
    case ReallyWantToHurtMe(Bool)
    case ReallyWantToMakeMeCry(Bool)
}

func doyou() -> DoYou { return .ReallyWantToHurtMe(true) }

func testChump() {
    assertme(doyou() == .ReallyWantToHurtMe)
}

GAH! Ok…

func testChump() {
    assertme(case .ReallyWantToHurtMe = doyou())
}

Oh… the case syntax isn’t a real expression…

func testChump() {
    if case .ReallyWantToHurtMe = doyou() { assertme(false) }
}

Yeah… that’s really less than ideal.

This is where I just get really freaking tired of working with associated enums and I do one of two things:

  1. Convert the associated enum into a struct that holds the values and a enum that is just the simple types. 2. Add getters for every case that returns an optional.

The first option has the severe limitation of only really working when the cases hold the same data types or nearly the same. It’s also a bit more annoying.

The second option is just super annoying to have to do. It signals a significant design issue with them. It’s also just a waste of time as well.

So this is what I do:

enum DoYou {
    case ReallyWantToHurtMe(Bool)
    case ReallyWantToMakeMeCry(Bool)

    var reallyWantToHurtMe: Bool? {
        if case let .ReallyWantToHurtMe(value) = doyou() { return value }
        return nil
    }

    var reallyWantToMakeMeCry: Bool? {
        if case let .ReallyWantToMakeMeCry(value) = doyou() { return value }
        return nil
    }
}

func testChump() {
    assertme(doyou().reallyWantToHurtMe != nil)
}

/cry

Sad State of Enums

Named Parameters

There’s a pretty interesting proposal discussion on swift-evolution right now: Naming Functions with Argument Labels.

I bring it up because it hits a bit close to my heart with regards to naming of functions named arguments. It’s my opinion that Swift should have diverged from ObjC here and treated named arguments properly. What I mean by that is to move the argument name within the function parameters completely.

So a function name like this:

func insertSubview(view, aboveSubview) {}

Would have become:

func insert(subview, aboveSubview)

The difference is the lack of the implicit _ on the first argument name. I bring this up (again) because of the given proposal shows well why I think the current convention stinks.

let fn = someView.insertSubview(_:aboveSubview:)

Ick! Why is that _ necessary. Oh‚Ķ right, because we’ve shoved the actual parameter name for that first item into the name of the function. ObjC did this for a compelling reason. Swift seems to simply follow that convention for what I can only presume to be convenience in the Swift to ObjC interop.

Too bad, this seems so much nicer to me:

let fn = someView.insert(subview:aboveView:)

Maybe someday…

Named Parameters

RE: Why Swift guard Should be Avoided

I saw this blog article, Why Swift guard Should Be Avoided, and it got me thinking about things I believe are fallacies but are continued to be talked about as the “right way to program”. I will preface this by saying that I don’t think there is a “right way” to program, but rather, there are trade-offs for particular paths that we chose to go down. Some of these paths provide better fruit than others. However, just as fruits have seasonality to them, some paths might not always produce the best fruit in all circumstances. Context matters. All that said, I still believe that are paths that never produce good fruit, and I think two of those paths are demonstrated in the linked blog article.

So, what are these bad paths (or as I call programming fallacies)?

  1. Functions should be between 6 and 10 lines 2. Single Responsibility means doing only one thing

The first is an arbitrary way to determine quality and complexity of code that holds no bearing in the actual domain of the problem. It also asserts that shorter code is better than longer code with no real presumption on the complexity of the shorter code. I believe that code clarity is far more important than code length.

The quote presented to defend this was from Robert C. Martin:

The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.

Here’s what I believe is a better philosophical position:

Functions should be as small as possible to do there job, but no smaller than that.

The other fallacy is that “single responsibility” means a single action. This leads you down the path of premature refactoring, which I’ll talk about a bit with examples from the post. A function should do a single task, but tasks are generally multi-step transactions. This should be completely obvious because we still need to have the vend() function; without it, we have to duplicate the logic everywhere in which a vend() must take place.

Pre-mature Refactoring

Ok, let’s get into the post a bit. Here’s the Swift code from Apple’s example:

struct Item {
    var price: Int
    var count: Int
}

enum VendingMachineError: ErrorType {
    case InvalidSelection
    case InsufficientFunds(coinsNeeded: Int)
    case OutOfStock
}

class VendingMachine {
    var inventory = [
        "Candy Bar": Item(price: 12, count: 7),
        "Chips": Item(price: 10, count: 4),
        "Pretzels": Item(price: 7, count: 11)
    ]

    var coinsDeposited = 0

    func dispense(snack: String) {
        print("Dispensing \(snack)")
    }

    func vend(itemNamed name: String) throws {
        guard var item = inventory[name] else {
            throw VendingMachineError.InvalidSelection
        }

        guard item.count > 0 else {
            throw VendingMachineError.OutOfStock
        }

        guard item.price <= coinsDeposited else {
            throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price - coinsDeposited)
        }

        coinsDeposited -= item.price
        --item.count
        inventory[name] = item
        dispense(name)
    }
}

And here’s the refactored version from the post:

func vend(itemNamed name: String) throws {
    let item = try validatedItemNamed(name)
    reduceDepositedCoinsBy(item.price)
    removeFromInventory(item, name: name)
    dispense(name)
}

private func validatedItemNamed(name: String) throws -> Item {
    let item = try itemNamed(name)
    try validate(item)
    return item
}

private func reduceDepositedCoinsBy(price: Int) {
    coinsDeposited -= price
}

private func removeFromInventory(var item: Item, name: String) {
    --item.count
    inventory[name] = item
}

private func itemNamed(name: String) throws -> Item {
    if let item = inventory[name] {
        return item
    } else {
        throw VendingMachineError.InvalidSelection
    }
}

private func validate(item: Item) throws {
    try validateCount(item.count)
    try validatePrice(item.price)
}

private func validateCount(count: Int) throws {
    if count == 0 {
        throw VendingMachineError.OutOfStock
    }
}

private func validatePrice(price: Int) throws {
    if coinsDeposited < price {
        throw VendingMachineError.InsufficientFunds(coinsNeeded: price - coinsDeposited)
    }
}

Let’s break it down:

vend(itemNamed name: String) throws

The author suggests that the refactored version is better. But here’s the first thing to note: the responsibility of the function has not changed; it is still responsible for doing the same thing it did before. So in the first regard, nothing should have changed from an API usage standpoint. This is vital because when we refactor functionality, this is the actual goal: to break about couple functionality that didn’t belong together.

private func validatedItemNamed(name: String) throws -> Item

I actually don’t know what this is supposed to do. In order to follow what is going on, I need to actually read through the code all of the code that it calls. Doing that, I can see that it does the following:

  1. Ensures the item is in the dictionary 2. That the count of items is not zero 3. That the number of coins deposited is greater than or equal to the price of the item

However, this took four functions and three levels of function calls to achieve. The oversight in this approach is that it is inherently fragile because it makes use of four functions to achieve it’s goal. A change to any single function can have a ripple effect on unintended side-effects.

Example: The vending machine needs a new function, addItem(). It’s purpose is to allow additional items to be added to the vending machine. However, there are some constraints we want to add for new items:

  1. The name must not be empty 2. The name must be word-capitalized (e.g. Big Candy Bar) 3. The price must be less than 100

I can pretty much guarantee you that the validateItem() function is going to be updated here to add these requirements. So not only are we going to be validating things that we simply don’t care about on ever call to vend(), if there is a data already in the vending machine that doesn’t already meet these requirements, the vend() is going to fail.

This may seem like a contrived example, but it absolutely is not. I’ve had to fix issues like this in real code because of this exact type of refactoring.

reduceDepositedCoinsBy(price: Int)

This function will lead to data corruption. It makes the assumption that validate() has been called. This function, if we’re going to actually have it, should actually do the verification that this is a legal operation. Otherwise, there is absolutely no purpose for it.

removeFromInventory(var item: Item, name: String)

Same comments apply here as well: data corruption!

itemNamed(name: String) throws -> Item

This one is an interesting one. If Swift had throwable subscripts, then this wouldn’t be necessary. However, I think in principle, this one is good, but the implementation is prone to bugs. This is the poster child for the guard statement.

private func itemNamed(name: String) throws -> Item {
    guard let item = inventory[name] {
        throw VendingMachineError.InvalidSelection
    }
    return item
}

This is objectively better as it ensures that the only code-path that can exist after the guard is one where the dictionary actually has the item. If also ensures that if the dictionary doesn’t have the item, we error out early.

Summary

Be wary of refactoring to meet arbitrary goals. When that is the purpose of the refactoring, it is very easy to get into a spot that you’ve actually created more complexity and introduced more error paths in your code.

My guiding principle: a function should handle it’s responsibility and only its responsibility. The number of steps for that responsibility is mostly immaterial.

RE: Why Swift guard Should be Avoided

Efficient Mutation

Here's the thing – I'm not very good at the whole concept of dealing with non-mutating data. Partly because I have a super difficult time understanding how you can write programs as the primary function of a program is to mutate data. So it's hard for me to grok the reason for design decisions such as "no pointers" and type-defined value/reference semantics. To me, they are actually a detriment to understanding how a program works.

So, I thought I'd post this to see if I can get some help from the community. I'll be glad to be corrected on this issue as I genuinely do not understand why there is this huge strive for immutable data everywhere.

Disclaimer: I completely understand why portions of your code would use immutable data; protecting yourself or others from accidentally causing side-effects is usually a good thing. That's not what I'm asking about though.

Ok, so what's the problem? That's easy: a syntax tree. I always find it best to ground my examples in real-world examples, and as I'm working on a programming language (Proteus) in my spare time, this seems like a great candidate.

The question is: how can I build up a tree over time efficiently without mutating but by retrieving new copies of the data? Further, how can I modify just a portion of the tree without needing to perform a copy of the entire tree?

It's the latter question that I'm really more interested in. I can completely see how the compiler could optimize away the copy while a type is being additively modified, especially since there are no other references to it. However, let's say you're building a code editor and you change the name of a function. There's no reason to re-parse the entire file; you know the location of the function in the file and where it sits in the AST, so the parse should be able to just parse the surrounding change and apply the delta to the tree.

Another way that I think about this problem is through the lens of a stream of changes that happen to the tree over time. So let's say we have the following stream:

  1. Parse top-level node (delta: add root node)
  2. Parse func decl (delta: add child to root node)
  3. Parse func body (delta: add children to func decl node)

Right, these are some very high-level deltas. With these three deltas, I don't see how to avoid the copy in the non-mutable world of the top-level node multiple times. In the world of mutation, I'd simply append the child to the parent for each of these deltas.

Am I just misunderstanding something?

To me, the efficiency of the program is extremely important. That's the time that the user is going to spend waiting for your code to run; it's important.

Efficient Mutation

Swift and Visual Studio Code

If you've been living under a rock, you might not know that Microsoft released a new editor (focused on web development): Visual Studio Code.

So… is it really just for web development? Honestly, it doesn't matter if it starts out that way because the thing that Microsoft tends to always get right is extensibility. We'll be able to start building plug-ins as the product matures to enable all sorts of development, including Swift!

Syntax Highlighting

Ok, the first thing that we need are the nice colors! This is actually fairly trivial to do:

  1. Open up the package contents of the Visual Studio Code app 2. Navigate to Contents/Resources/app/plugins 3. Create a new folder: vs.languages.swift 4. Place these three files into the created folder:
    1. swiftDef.js
    2. swiftMain.js
    3. ticino.plugin.json 5. Restart Visual Studio Code and open a Swift file!

You should see something like this:

Swift with basic syntax highlighting.

Note that this is just the most basic of highlighting that supports basic comments, strings, and keywords. More to come later!

Building

Next up, build errors! Again, this is also quite trivial to setup. You'll need to create a new build task. You can do this in a couple of ways. The easiest is:

  1. ‚åòP to bring up the command palette 2. Type build and press RETURN 3. There will be a prompt that you have not tasks; create the task 4. This will create a .settings folder with a tasks.json file

The contents of the file should be:

{
    "version": "0.1.0",
    "command": "swiftc",
    "showOutput": "silent",

    "args": ["main.swift"],

    "problemMatcher": {
        "pattern": {
            "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
            "file": 1,
            "line": 2,
            "column": 3,
            "severity": 4,
            "message": 5
        }
    }
}

Now, you can press ‚áß‚åòB now to build. If you have an error, press ‚áß‚åòM to show the error pane.

Swift with a build error shown.

Next Steps

I'll probably be taking a look at making the editing experience better by playing around with the options for syntax highlighting. I also want to take a look at building a language service, though, officially this is not yet supported.

Goodie Bin

Ok… if you want to contribute to this, I've actually posted a fill GitHub repo here: https://github.com/owensd/vscode-swift.

What I actually have done, instead of creating a directory, is create a link within the Visual Studio Code package to my repo location on disk.

  1. cd /Applications/Visual\ Studio\ Code.app/Contents/Resources/app/plugins 2. ln -s <path/to/repo> vs.languages.swift 3. Restart Visual Studio Code

Voilà!

Swift and Visual Studio Code