Value Add – Bring Something to the Table

There was a comment on my Programming Theory and Practice blog article about a reactive solution for interacting with IOHIDManager. The full gist of it can be found here:

My thoughts on it can be summed up essentially as:

  1. It requires another library to actually see the code that is going on (the ChannelZ lib from the author), that is bad.
  2. The solution requires bridging from Swift to ObjC back to Swift again, that is bad (though it cannot currently be avoided).
  3. It is no better than the ObjC or C

The last point is the real kicker for me, especially as of late. If I'm going to invest in a new technology, I want to understand the value that I'm getting back from it. In other words: am I getting a good ROI (return on investment) from it?

The thing is, we can write the same "reactive-style" API today, in C or C compiler). To me, this is very valuable and is currently a significant negative (really, a potential deal-breaker for me) against Swift1. We don't know the plans for Swift, so it's hard to say what is going to happen here, and I am personally not interested in any of the managed ports I've been seeing for other platforms.

Thinking About the API

The API for the reactive-style needs to care about three basic things:

  1. connect – we need to know when a new device has been connected
  2. disconnect – we need to know when a device has been disconnected
  3. input – we need to know when the input has changed

When we implement these things, we can do so in a pull, push, or a push-pull manner. My primary use case is for a game, so I'm going to use the pull model. This means that I want my input to actually be a collection of input values since the last time I requested them. I'm also going to ignore connect and disconnect for this example as they are really not that interesting and adds very little to this example.

The API is starting to look like this:

struct DeviceManager {
    var input: [Input]
    let hidManager: IOHIDManagerRef

The C

struct DeviceManager {
    std::vector<Input> input;
    IOHIDManagerRef hidManager;

Let's also say that Input looks like this:

enum Input {
    case Mouse(x: Int, y: Int, buttons: [ButtonState] /* only want max of 5 */)
    case Keyboard(keyCode: VirtualKey, state: KeyState)

To model that in C

namespace DeviceType {
    enum Type { Mouse, Keyboard };

struct Input {
    DeviceType::Type type;

    union {
        struct { /* Mouse */
             int x;
             int y;
             ButtonState buttons[5];
        struct { /* Keyboard */
            VirtualKey keyCode;
            KeyState state;

Clearly, the Swift version has some nice wins on syntax here.

Now, I said that I'm using the pull-model, so I have some update function:

func update() { /* The signature doesn't matter... */
    let mouseInputs = filter(manager.inputs) {
        switch ($0) {
             case let .Mouse(_): return true
             default: return false
    // do something interesting with the filtered mouse signals

I'm not sure if there is a better way to do that check with associated enum values, but it kinda sucks. The C

void update() {
    auto mouseInputs = filter(manager.inputs, [] (DeviceInput input) {
        return input.type == DeviceType.Mouse;
    // do something interesting with the filtered mouse signals

Ironically, the C

What's the Value?

The above example is only a subset of the full solution, but it is not really that far off from being complete. For me, I've been looking at and really wondering what the ROI is going to be for me to fully invest in learning and using Swift. Honestly, I'm not sure.

At this point, it is really starting to look like that I should just go back to C11 features, there is really not a whole lot that Swift can do over C

  1. Lack of code portability
  2. Lack of code interoperability
  3. Lack of full memory control

Yes, it is true that each of these also has a cost associated with it in regards to C

Remember, Swift is still in its infancy – it is going to need to get a lot more sophisticated to realize its aspirations, especially to become a "systems level language".

For me personally, I think it is going to be a much better use of my time writing modern C

Your mileage may vary.

  1. You need to evaluate this for your own needs; this type of cross-platform sharing may be of little to no value for you.
Value Add – Bring Something to the Table