Created
January 6, 2015 17:12
-
-
Save landonf/3e04ea3c7b13f68ab746 to your computer and use it in GitHub Desktop.
consequentialism was an experiment in improving ObjC with C++ templates
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@interface SeqTests : XCTestCase @end | |
@implementation SeqTests | |
/* Construction examples */ | |
- (void) testConstruction { | |
} | |
/* Some example uses */ | |
- (void) testExample { | |
/* A simple example of typesafe map/filter/flatten/foreach operations. Each step is type-checked based on inferring | |
* the return type of the previous step; unlike a pure ObjC solution, the compiler will raise an error if you | |
* return or provide a block that operates on the wrong type. */ | |
{ | |
/* Filter out locked campains, extract their venues, flatten them into a single sequence, and log their regions. */ | |
self.campaigns.filter(^(PPCampaign *campaign) { | |
return campaign.locked; | |
}).map(^(PPCampaign *campaign) { | |
return campaign.venues; | |
}).flatten().foreach(^(PPVenue *venue) { | |
NSLog(@"This entire process was fully type-checked, with inferred types! %@", venue.region); | |
}); | |
} | |
/* If we explicitly declare our types (rather than relying on type inference), the above can be written in long-form | |
* as: */ | |
{ | |
/* Fetch all campaigns */ | |
Seq<PPCampaign *> campaigns = self.campaigns; | |
/* Filter out all unlocked campaigns */ | |
Seq<PPCampaign *> lockedCampaigns = campaigns.filter(^BOOL (PPCampaign *item) { | |
return item.locked; | |
}); | |
/* Fetch the list of venues from each campaign */ | |
Seq<Seq<PPVenue*>> allVenues = lockedCampaigns.map(^Seq<PPVenue*> (PPCampaign *campaign) { | |
return campaign.venues; | |
}); | |
/* Flatten the list of venues */ | |
Seq<PPVenue*> venues = allVenues.flatten(); | |
/* Log the venue's regions */ | |
venues.foreach(^void (PPVenue *venue) { | |
NSLog(@"This was a much more verbose way to do the exact same thing: %@", venue.region); | |
}); | |
} | |
/* Lastly, if we were to do this in pure ObjC, this would be the equivalent. | |
* | |
* The code is nearly as short as the first one, but: | |
* - The types returned from the Objective-C container classes are `id', and are not checked by the compiler. | |
* - We're forced to use mutable types to gather the results. | |
* - The stages are not easily composed / re-composed. | |
* | |
* NOTE: The toObjC() calls are an artifact of our model objects returning Seq<T> types, which require an explicit | |
* call to acquire access to the backing plain ObjC representation. | |
*/ | |
{ | |
/* Extract the venues from all locked campaigns. */ | |
NSMutableArray *venues = [[NSMutableArray alloc] init]; | |
for (PPCampaign *campaign in self.campaigns.toObjC()) { | |
if (!campaign.locked) { | |
continue; | |
} | |
for (PPVenue *venue in campaign.venues.toObjC()) { | |
[venues addObject: venue]; | |
} | |
} | |
/* Log the venue's regions */ | |
for (PPVenue *venue in venues) { | |
NSLog(@"This the ObjC way: %@", venue.region); | |
} | |
} | |
} | |
- (Seq<PPCampaign*>) campaigns { | |
Seq<NSString*>(@"String", @"String"); | |
return Seq<PPCampaign*>( | |
[[PPCampaign alloc] initWithVenues: Seq<PPVenue*>( | |
[[PPVenue alloc] initWithRegion: @"North America"], | |
[[PPVenue alloc] initWithRegion: @"South America"] | |
) locked: NO], | |
[[PPCampaign alloc] initWithVenues: Seq<PPVenue*>( | |
[[PPVenue alloc] initWithRegion: @"Europe"], | |
[[PPVenue alloc] initWithRegion: @"Happy Fun Zone"] | |
) locked: YES] | |
); | |
} | |
@end | |
@implementation PPVenue | |
- (instancetype) initWithRegion: (NSString *) region { | |
if ((self = [super init]) == nil) return nil; | |
_region = region; | |
return self; | |
} | |
@end | |
@implementation PPCampaign | |
- (instancetype) initWithVenues: (Seq<PPVenue*>) venues locked: (BOOL) locked { | |
if ((self = [super init]) == nil) return nil; | |
_venues = venues; | |
_locked = locked; | |
return self; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment