Getting better at doing it wrong

For around a month at the end of last year, I kept a long text note called “doing doing it wrong right”. I was trying to understand error handling in programming, look at some common designs and work out a plan for cleaning up some error-handling code I was working with myself (mercifully someone else, with less analysis paralysis, has taken on that task now).

Deliciously the canonical writing in this field is by an author with the completely apt name Goodenough. His Structured Exception Handling and Exception Handling: Issues and a Proposed Notation describe the problem pretty completely and introduce the idea of exceptions that can be thrown on an interesting condition and caught at the appropriate level of abstraction in the caller.

As an aside, his articles show that exception handling can be used for general control flow. Your long-running download task can throw the “I’m 5% complete now” exception, which is caught to update the UI before asking the download to continue. Programming taste moved away from doing that.

In the Cocoa world, exceptions have never been in favour, probably because they’re too succinct. In their place, multi-if statement complex handling code is introduced:

NSError *error = nil;
id thing = [anObject giveMeAThing:&error];
if (!thing) {
  [self handleError:error];
  return;
}
id otherThing = [thing doYourThing:&error];
if (!otherThing) {
  [self handleError:error];
  return;
}
id anotherThing = [otherThing someSortOfThing:&error];

…and so it goes.

Yesterday in his NSMeetup talk on Swift, Saul Mora reminded me of the nil sink pattern in Objective-C. Removing all the error-handling from the above, a fluent (give or take the names) interface would look like this:

id anotherThing = [[[anObject giveMeAThing] doYourThing] someSortOfThing];

The first method in that chain to fail would return nil, which due to the message-sink behaviour means that everything subsequent to it preserves the nil and that’s what you get out. Saul had built an equivalent thing with option types, and a function Maybe a -> (a -> Maybe b) -> Maybe b to hide all of the option-unwrapping conditionals.

Remembering this pattern, I think it’s possible to go back and tidy up my error cases:

NSError *error = nil;
id anotherThing = [[[anObject giveMeAThing:&error]
                               doYourThing:&error]
                           someSortOfThing:&error];
if (!anotherThing) {
  [self handleError:error];
}

Done. Whichever method goes wrong sets the error and returns nil. Everything after that is sunk, which crucially means that it can’t affect the error. As long as the errors generated are specific enough to indicate what went wrong, whether it’s possible to recover (and if so, how) and whether anything needs cleaning up (and if so, what) then this approach is…good enough.

Hiding behind messages

A problem I think about every so often is how to combine the software design practice of hiding implementations behind interfaces with the engineering practice of parallel execution. What are the trade-offs between making parallelism explicit and information hiding? Where are some lines that can be drawn?

Why do we need abstractions for this stuff, when the libraries we have already work? Those libraries make atomic features like threads and locks explicit, or they make change of control flow explicit, and those are things we can manage in one place for the benefit of the rest of our application. Nobody likes to look at the dispatch terrace:

    });
  });
});

Previous solutions have involved object confinement, where every object has its own context and runs its code there, and the command bus, where you ask for work to be done but don’t get to choose where.

Today’s solution is a bit more explicit, but not much. For every synchronous method, create an asynchronous version:

@interface MyObject : Awaitable

- (NSString *)expensiveCalculation;
- async_expensiveCalculation;

@end

@implementation MyObject

- (NSString *)expensiveCalculation
{
  sleep(5);
  return @"result!";
}

@end

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    MyObject *o = [MyObject new];
    id asyncResult = [o async_expensiveCalculation];
    NSLog(@"working...");
    // you could explicitly wait for the calculation...
    NSLog(@"Result initial: %@", [[asyncResult await]   substringToIndex:1]);
    // ...but why bother?
    NSLog(@"Shouty result: %@", [asyncResult uppercaseString]);
  }
  return 0;
}

This is more of a fork-and-join approach than fire and forget. The calling thread carries on running until it actually needs the result of the calculation, at which point it waits (if necessary) for the callee to complete before continuing. It’ll be familiar to programmers on other platforms as async/await.

The implementation is – blah blah awesome power of the runtime – a forwardInvocation: method that looks for messages with the async marker, patches their selector and creates a proxy object to invoke them in the background. That proxy is then written into the original invocation as its return value. Not shown: a pretty straightforward category implementing -[NSInvocation copyWithZone:].

@implementation Awaitable

- (SEL)suppliedSelectorForMissingSelector:(SEL)aSelector
{
  NSString *selectorName = NSStringFromSelector(aSelector);
  NSString *realSelectorName = nil;
  if ([selectorName hasPrefix:@"async_"]) {
    realSelectorName = [selectorName substringFromIndex:6];
  }
  return NSSelectorFromString(realSelectorName);
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
  NSMethodSignature *aSignature =   [super methodSignatureForSelector:aSelector];
  if (aSignature == nil) {
    aSignature =    [super methodSignatureForSelector:[self suppliedSelectorForMissingSelector:aSelector]];
  }
  return aSignature;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
  SEL trueSelector =    [self suppliedSelectorForMissingSelector:[anInvocation selector]];
  NSInvocation *cachedInvocation = [anInvocation copy];
  [cachedInvocation setSelector:trueSelector];
  CBox *box = [CBox cBoxWithInvocation:cachedInvocation];
  [anInvocation setReturnValue:&box];
}

@end

Why is the proxy object called CBox? No better reason than that I built this while reading a reflection on Concurrent Smalltalk where that’s the name of this object too.

@interface CBox : NSProxy

+ (instancetype)cBoxWithInvocation:(NSInvocation *)inv;
- await;

@end

@implementation CBox
{
  NSInvocation *invocation;
  NSOperationQueue *queue;
}

+ (instancetype)cBoxWithInvocation:(NSInvocation *)inv
{
  CBox *box = [[self alloc] init];
  box->invocation = [inv retain];
  box->queue = [NSOperationQueue new];
  NSInvocationOperation *op = [[NSInvocationOperation alloc]    initWithInvocation:inv];
  [box->queue addOperation:op];
  return [box autorelease];
}

- init
{
  return self;
}

- await
{
  [queue waitUntilAllOperationsAreFinished];
  id returnValue;
  [invocation getReturnValue:&returnValue];
  return [[returnValue retain] autorelease];
}

- (void)dealloc
{
  [queue release];
  [invocation release];
  [super dealloc];
}

- forwardingTargetForSelector:(SEL)aSelector
{
  return [self await];
}

@end

You don’t always need some huge library to clean things up. Here are about 70 lines of Objective-C that abstract an implementation of concurrent programming and stop my application code from having to interweave the distinct responsibilities of what it’s trying to do and how it’s trying to do it.

Fun and games (with rewritten rules) in Objective-C

An object-oriented programming environment is not a set of rules. Programs do not need to be constructed according to the rules supplied by the environment. An object-oriented environment includes tools for constructing new rules, and programs can use these to good effect. Let’s build multiple method inheritance for Objective-C, to see a new set of rules.

The goal

Given three classes, A, B, and C:

@interface A : NSObject

-(NSInteger)a;
-(NSInteger)double:(NSInteger)n;

@end

@implementation A

-(NSInteger)a { return [self double:6]; }

@end

@interface B : NSObject

-(NSInteger)b;

@end

@implementation B

-(NSInteger)b { return 30; }

@end

@interface C : NSObject

-c;

@end

@implementation C

-(NSInteger)double:(NSInteger)a
{
  return a*2;
}

-c { return @([self a] + [self b]); }

@end

We want to find the value of a C instance’s c property. That depends on its values of a and b, but that class doesn’t have those methods. We should add them.

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    C *c = [C new];
    [c addSuperclass:[A class]];
    [c addSuperclass:[B class]];
    NSLog(@"The answer is %@", c.c);
  }
}

We want the following output:

2015-02-17 20:23:36.810 Mixins[59019:418112] The answer is 42

Find a method from any superclass

Clearly there’s some chicanery going on here. I’ve changed the rules: methods are no longer simply being looked up in a single class. My instance of C has three superclasses: A, B and NSObject.

@interface NSObject (Mixable)

- (void)addSuperclass:(Class)aSuperclass;

@end

@implementation NSObject (Mixable)

-superclasses
{
  return objc_getAssociatedObject(self, "superclasses");
}

- (void)addSuperclass:(Class)aSuperclass
{
  id superclasses = [self superclasses]?:@[];
  id newSupers = [superclasses arrayByAddingObject:aSuperclass];
  objc_setAssociatedObject(self, "superclasses", newSupers, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (Class)superclassForSelector:(SEL)aSelector
{
  __block Class potentialSuperclass = Nil;
  [[self superclasses] enumerateObjectsUsingBlock:^(Class aClass, NSUInteger idx, BOOL *stop) {
    if ([aClass instancesRespondToSelector:aSelector])
    {
      potentialSuperclass = aClass;
      *stop = YES;
    }
  }];
  return potentialSuperclass;
}

- (NSMethodSignature *)original_methodSignatureForSelector:(SEL)aSelector
{
  NSMethodSignature *signature = [self original_methodSignatureForSelector:aSelector];
  if (signature)
  {
    return signature;
  }
  Class potentialSuperclass = [self superclassForSelector:aSelector];
  return [potentialSuperclass instanceMethodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
  SEL aSelector = [anInvocation selector];
  Class potentialSuperclass = [self superclassForSelector:aSelector];
  [anInvocation invokeSuperImplementation:potentialSuperclass];
}

+ (void)load
{
  if (self == [NSObject class])
  {
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(original_methodSignatureForSelector:)),
                                   class_getInstanceMethod(self, @selector(methodSignatureForSelector:)));
  }
}

@end

Now invoke that method.

When you write [super foo], the Objective-C runtime needs to send a message to your object but tell the resolution machinery to look at the superclass for the method implementation, not at the current class. It uses a function objc_msgSendSuper to do this. In this case, I don’t have the superclass: I have a superclass, one of potentially many. So what I need to do is more general than what messaging super does.

Luckily for me, objc_msgSendSuper is already sufficiently general. It receives a pointer to self, just like the usual objc_msgSend, but in addition it receives a pointer to the class to be used as the superclass. By controlling that class pointer, I can tell the system which superclass to use.

A category on NSInvocation calls objc_msgSendSuper with the appropriate arguments to get the correct method from the correct class. But how can it call the function correctly? Objective-C messages could receive any number of arguments of any type, and return a value of any type. Constructing a function call when the parameters are discovered at runtime is the job of libffi, which is used here (not shown: a simple, if boring, map of Objective-C value encodings to libffi type descriptions).

@interface NSInvocation (SuperInvoke)

-(void)invokeSuperImplementation:(Class)superclass;

@end

@implementation NSInvocation (SuperInvoke)

- (BOOL)isVoidReturn
{
  return (strcmp([[self methodSignature] methodReturnType], "v") == 0);
}

-(void)invokeSuperImplementation:(Class)superclass
{
  NSMethodSignature *signature = [self methodSignature];
  if (superclass)
  {
    struct objc_super super_class = { .receiver = [self target],
      .super_class = superclass };
    struct objc_super *superPointer = &super_class;
    ffi_cif callInterface;
    NSUInteger argsCount = [signature numberOfArguments];
    ffi_type **args = malloc(sizeof(ffi_type *) * argsCount);
    for (int i = 0; i < argsCount; i++) {
      args[i] = [self ffiTypeForObjCType:[signature getArgumentTypeAtIndex:i]];
    }
    ffi_type *returnType;
    if ([self isVoidReturn]) {
      returnType = &ffi_type_void;
    }
    else {
      returnType = [self ffiTypeForObjCType:[signature methodReturnType]];
    }
    ffi_status status = ffi_prep_cif(&callInterface,
                                     FFI_DEFAULT_ABI,
                                     (unsigned int)[signature numberOfArguments],
                                     returnType,
                                     args);
    if (status != FFI_OK) {
      NSLog(@"I can't make an FFI frame");
      free(args);
      return;
    }

    void *argsBuffer = malloc([signature frameLength]);
    int cursor = 0;
    cursor += args[0]->size;
    void **values = malloc([signature numberOfArguments] * sizeof(void  *));
    values[0] = &superPointer;

    for (int i = 1; i < [signature numberOfArguments]; i++) {
      values[i] = (argsBuffer + cursor);
      [self getArgument:values[i] atIndex:i];
      cursor += args[i]->size;
    }
    if ([self isVoidReturn]) {
      ffi_call(&callInterface, objc_msgSendSuper, NULL, values);
    } else {
      void *result = malloc(returnType->size);
      ffi_call(&callInterface, objc_msgSendSuper, result, values);
      [self setReturnValue:result];
      free(result);
    }
    free(args);
    free(values);
    free(argsBuffer);
  }
}

@end

Conclusion

You’ve seen this conclusion before: blah blah awesome power of the runtime. It doesn’t just let you do expressive things in the Objective-C game, it lets you define a better game.

Objective-Curry

Sadly it’s not called Schoenfinkeling, but that’s the name of the
person who noticed that there’s no reason to ever have a function with
more than one argument. What you think is a function with two
arguments is actually a function with one argument that returns a
function with one argument, this second function closing over the
first argument and acting perhaps on both.

This is, of course, famed for its application (pardon the pun) to Object-Oriented
Programming. We can take a class like this:

@interface NamePrinter : Curryable

- (void)printFirstName:(NSString *)first surname:(NSString *)last;
- (void)printFirstName:(NSString *)first age:(NSInteger)age;
- (void)printFirstName:(NSString *)first middle:(NSString *)middle surname:(NSString *)last;

@end

and use it like this:

int main(int argc, char *argv[]) {
  @autoreleasepool {
    id printer = [[NamePrinter new] autorelease];
    id curried = [printer printFirstName:@"Graham"];
    [curried surname:@"Lee"];
    [curried surname:@"Greene"];
    [curried surname:@"Garden"];
    [curried age:18];

    id alex = [printer printFirstName:@"Alexander"];
    id alexG = [alex middle:@"Graham"];
    [alexG surname:@"Bell"];
  }
}

(your compiler probably complains at this point that it doesn’t know
what you’re up to. Of course, you know better.)

We’ll get results like this:

2015-02-13 00:57:57.421 CurrySauce[41877:134228] Graham Lee
2015-02-13 00:57:57.421 CurrySauce[41877:134228] Graham Greene
2015-02-13 00:57:57.421 CurrySauce[41877:134228] Graham Garden
2015-02-13 00:57:57.422 CurrySauce[41877:134228] Graham is 18 years old
2015-02-13 00:57:57.422 CurrySauce[41877:134228] Alexander Graham Bell

OK, we don’t actually get that for free. There’s some secret sauce I
haven’t shown you: secret curry sauce.

Here be dragons

As with
all the best bits of Objective-C,
you need to turn off the automatic reference counting to do what
follows (you’ll have already seen a call to -autorelease above). ARC
works wonders when you try to write Java in Objective-C, give or take
the strong-weak-strong tango. It isn’t so helpful when you try to
write Objective-C in Objective-C.

Partial application

The NamePrinter class knows that you might call it with a partial
application, so it checks whether the selector you sent in your
message matches the prefix of any method it knows. If it does, and the
return type and argument types in this prefix can be uniquely
determined, then it creates a proxy to listen for the rest of the
application.

The restrictions on types are there due to the way that Objective-C
deals with C types in message sending. It’d be a lot easier to do this
in Ruby or Smalltalk, where everything is an object reference: as
Objective-C needs to deal with C types of different sizes, you must be
able to construct a single invocation from the prefix selector.

int argumentsForSelector(SEL aSelector)
{
  const char *name = sel_getName(aSelector);
  int count = 0;
  while(*name != '\0') {
    if (*name++ == ':') {
      count++;
    }
  }
  return count;
}

@implementation Curryable

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
  NSMethodSignature *superSignature = [super methodSignatureForSelector:aSelector];
  if (superSignature) {
    return superSignature;
  }
  NSString *thisSelectorName = NSStringFromSelector(aSelector);
  NSMutableSet *signatures = [NSMutableSet set];
  int argCount = argumentsForSelector(aSelector);
  Class currentClass = [self class];
  while (currentClass != Nil) {
    unsigned int methodCount = 0;
    Method *methodList = class_copyMethodList(currentClass, &methodCount);
    for (int i = 0; i < methodCount; i++) {
      Method method = methodList[i];
      SEL anotherSelector = method_getName(method);
      NSString *selectorName = NSStringFromSelector(anotherSelector);
      if ([selectorName hasPrefix:thisSelectorName]) {
        NSMethodSignature *fullSignature = [self methodSignatureForSelector:anotherSelector];
        NSMutableString *constructedTypeSignature = [[@"@@:" mutableCopy] autorelease];
        for (int j = 2; j < argCount + 2; j++) {
          [constructedTypeSignature appendString:@([fullSignature getArgumentTypeAtIndex:j])];
        }
        [signatures addObject:[[constructedTypeSignature copy] autorelease]];
      }
    }
    free(methodList);
    currentClass = class_getSuperclass(currentClass);
  }
  if ([signatures count] != 1) {
    NSLog(@"curried selector does not uniquely match the type of any full selector prefix");
    return nil;
  }
  return [NSMethodSignature signatureWithObjCTypes:[[signatures anyObject] UTF8String]];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
  id curry = [CurrySauce curryTarget:self invocation:anInvocation];
  [anInvocation setReturnValue:&curry];
}

@end

All of that, just to return a proxy object.

Finish the application

This proxy also responds to unknown selectors, by trying to tack
them onto the end of the partially-applied selector. If that works,
and it ends up with a selector that the target recognises, then it
constructs the combined invocation, copies the arguments from the two
partial invocations, and invokes it on the target. If the combined
selector is supposed to return something then this proxy unpacks the
return value and puts it into the invocation it received, to ensure
that the caller picks it up.

SEL concatenateSelectors(SEL firstSelector, SEL secondSelector)
{
  NSString *firstPart = NSStringFromSelector(firstSelector);
  NSString *selectorName = [firstPart stringByAppendingString:NSStringFromSelector(secondSelector)];
  return NSSelectorFromString(selectorName);
}

@implementation CurrySauce
{
  id target;
  NSInvocation *invocation;
}

-initWithTarget:object invocation:(NSInvocation *)partialApplication
{
  target = [object retain];
  invocation = [partialApplication retain];
  return self;
}

+curryTarget:object invocation:(NSInvocation *)partialApplication
{
  return [[[self alloc] initWithTarget:object invocation:partialApplication] autorelease];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
  //special case for respondsToSelector
  if (aSelector == @selector(respondsToSelector:)) {
    return [target methodSignatureForSelector:aSelector];
  }
  SEL combinedSelector = concatenateSelectors([invocation selector], aSelector);
  NSMethodSignature *combinedSignature = [target methodSignatureForSelector:combinedSelector];
  if (combinedSignature != nil) {
    NSMutableString *completionType = [NSMutableString stringWithFormat:@"%s@:",[combinedSignature methodReturnType]];
    for (int i = argumentsForSelector([invocation selector]) + 2; i < argumentsForSelector(combinedSelector) + 2; i++) {
      [completionType appendFormat:@"%s",[combinedSignature getArgumentTypeAtIndex:i]];
    }
    return [NSMethodSignature signatureWithObjCTypes:[completionType UTF8String]];
  } else {
    return nil;
  }
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
  if ([anInvocation selector] == @selector(respondsToSelector:)) {
    [anInvocation invokeWithTarget:target];
    return;
  }
  SEL realSelector = concatenateSelectors([invocation selector], [anInvocation selector]);
  NSMethodSignature *signature = [target methodSignatureForSelector:realSelector];
  NSInvocation *combined = [NSInvocation invocationWithMethodSignature:signature];
  int argumentToSet = 2;
  void *argBuffer = malloc([[invocation methodSignature] frameLength]);
  for (int i = 2; i < [[invocation methodSignature] numberOfArguments]; i++) {
    [invocation getArgument:argBuffer atIndex:i];
    [combined setArgument:argBuffer atIndex:argumentToSet++];
  }
  free(argBuffer);
  argBuffer = malloc([[anInvocation methodSignature] frameLength]);
  for (int i = 2; i < [[anInvocation methodSignature] numberOfArguments]; i++) {
    [anInvocation getArgument:argBuffer atIndex:i];
    [combined setArgument:argBuffer atIndex:argumentToSet++];
  }
  free(argBuffer);

  [combined setTarget:target];
  [combined setSelector:realSelector];
  [combined invoke];
  if (strcmp([[combined methodSignature] methodReturnType], "v")) {
    void *returnBuffer = malloc([[combined methodSignature] methodReturnLength]);
    [combined getReturnValue:returnBuffer];
    [anInvocation setReturnValue:returnBuffer];
    free(returnBuffer);
  }
}

- (void)dealloc
{
  [target release];
  [invocation release];
  [super dealloc];
}

@end

Conclusion

Blah blah awesome power of the runtime, I suppose. It’s pretty cool
that you can do this sort of thing in 150 lines of ObjC. I doubt many
people would want to use it for reals though.

Like Java, only functional

An idea that clarified itself to me in discussion today is that Swift is to Functional Programming as Java is to Object-Oriented Programming: it is the thing that lets you write C and pretend you’ve adopted some posh-sounding “paradigmatic” non-imperative approach to programming.

I thought this was true shortly before lunch, but now climb partway down from the high horse. Swift is to Functional Programming as Java is to Object-Oriented Programming is still true. However Swift is to C# 3.0 as Java is to Objective-C.

Quotes on JavaScript

Derek Jones, from the PL advent calendar ‘J’ entry:

Javascript would not have existed without the Internet and its ‘design’ must be a contender for the most costly software mistake [ever] made.

Me, 14 months ago:

Fundamentally I fear a world in which programmers think JavaScript is acceptable. Partly because JavaScript, but mostly because when a language is introduced and people avoid it for ages, then just because some CEO says all future websites must use it they start using it, that’s not healthy. Objective-C was introduced and people avoided it for ages, then just because some CEO said all future apps must use it they started using it.

Clearly JavaScript is good enough for a broad set of uses. But then we should ask whether ‘good enough’ means unfurling the Mission Accomplished flag and calling it done. Apparently some people have similar feelings, but also the skill and inclination to do something about it.