Skip to content
This repository has been archived by the owner on Jan 25, 2019. It is now read-only.

Spring Cleaning #33

Closed
wants to merge 16 commits into from
Closed
2 changes: 2 additions & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Ullrich Schäfer
Max Winde
Alexis Kinsella
Amiel Martin
Steve Chung
Robert Böhnke
12 changes: 11 additions & 1 deletion Underscore.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@
54A3DCBC154DD4BF00387DE3 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0430;
LastUpgradeCheck = 0460;
ORGANIZATIONNAME = "Robert Böhnke";
};
buildConfigurationList = 54A3DCBF154DD4BF00387DE3 /* Build configuration list for PBXProject "Underscore" */;
Expand Down Expand Up @@ -327,6 +327,10 @@
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
Expand All @@ -339,6 +343,7 @@
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
SDKROOT = iphoneos;
Expand All @@ -351,11 +356,16 @@
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
SDKROOT = iphoneos;
Expand Down
2 changes: 2 additions & 0 deletions Underscore/USArrayWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,6 @@
@property (readonly) BOOL (^all)(UnderscoreTestBlock block);
@property (readonly) BOOL (^any)(UnderscoreTestBlock block);

@property (readonly) USArrayWrapper *(^sort)(UnderscoreSortBlock block);

@end
23 changes: 20 additions & 3 deletions Underscore/USArrayWrapper.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,27 @@ - (id)last

- (USArrayWrapper *)flatten
{
__weak NSArray *array = self.array;
__block NSArray *(^flatten)(NSArray *) = ^NSArray *(NSArray *input) {
NSMutableArray *result = [NSMutableArray array];

for (id obj in input) {
if ([obj isKindOfClass:[NSArray class]]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
[result addObjectsFromArray:flatten(obj)];
#pragma clang diagnostic pop
} else {
[result addObject:obj];
}
}

// If the outmost call terminates, nil the reference to flatten to break
// the retain cycle
if (input == array) {
flatten = nil;
}

return result;
};

Expand Down Expand Up @@ -215,10 +225,9 @@ - (USArrayWrapper *)shuffle

- (USArrayWrapper *)uniq
{
NSSet* uniqSet = [NSSet setWithArray:self.array];
NSArray* result = [uniqSet allObjects];
NSOrderedSet *set = [NSOrderedSet orderedSetWithArray:self.array];

return [[USArrayWrapper alloc] initWithArray:result];
return [[USArrayWrapper alloc] initWithArray:[set array]];
}

- (id (^)(UnderscoreTestBlock))find
Expand Down Expand Up @@ -284,4 +293,12 @@ - (USArrayWrapper *)uniq
};
}

- (USArrayWrapper *(^)(UnderscoreSortBlock))sort
{
return ^USArrayWrapper *(UnderscoreSortBlock block) {
NSArray *result = [self.array sortedArrayUsingComparator:block];
return [[USArrayWrapper alloc] initWithArray:result];
};
}

@end
2 changes: 2 additions & 0 deletions Underscore/USConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ typedef id (^UnderscoreArrayMapBlock)(id obj);

typedef void (^UnderscoreDictionaryIteratorBlock)(id key, id obj);
typedef id (^UnderscoreDictionaryMapBlock)(id key, id obj);

typedef NSComparisonResult (^UnderscoreSortBlock)(id a, id b);
2 changes: 2 additions & 0 deletions Underscore/Underscore+Functional.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
+ (BOOL (^)(NSArray *array, UnderscoreTestBlock block))all;
+ (BOOL (^)(NSArray *array, UnderscoreTestBlock block))any;

+ (NSArray *(^)(NSArray *array, UnderscoreSortBlock block))sort;

#pragma mark NSDictionary style methods

+ (USDictionaryWrapper *(^)(NSDictionary *dictionary))dict;
Expand Down
7 changes: 7 additions & 0 deletions Underscore/Underscore+Functional.m
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ @implementation Underscore (Functional)
};
}

+ (NSArray *(^)(NSArray *, UnderscoreSortBlock))sort
{
return ^(NSArray *array, UnderscoreSortBlock block) {
return Underscore.array(array).sort(block).unwrap;
};
}

#pragma mark NSDictionary shortcuts

+ (USDictionaryWrapper *(^)(NSDictionary *))dict
Expand Down
6 changes: 2 additions & 4 deletions Underscore/Underscore.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@
#import "USArrayWrapper.h"
#import "USDictionaryWrapper.h"

#if !__has_feature(objc_arc)
# error Underscore.m requires Automatic Reference Counting to be enabled
#endif

@interface Underscore : NSObject

+ (UnderscoreTestBlock(^)(UnderscoreTestBlock))negate;
Expand All @@ -45,6 +41,8 @@
+ (UnderscoreTestBlock)isNumber;
+ (UnderscoreTestBlock)isString;

+ (UnderscoreSortBlock)compare;

- (id)init __deprecated;

@end
Expand Down
11 changes: 11 additions & 0 deletions Underscore/Underscore.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@

#import "Underscore.h"

#if !__has_feature(objc_arc)
# error Underscore.m requires Automatic Reference Counting to be enabled
#endif

@implementation Underscore

+ (UnderscoreTestBlock (^)(UnderscoreTestBlock))negate
Expand Down Expand Up @@ -81,6 +85,13 @@ + (UnderscoreTestBlock)isString
};
}

+ (UnderscoreSortBlock)compare
{
return ^NSComparisonResult(id a, id b){
return [a compare:b];
};
}

- (id)init
{
return [super init];
Expand Down
10 changes: 10 additions & 0 deletions UnderscoreTests/HelperTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,14 @@ - (void)testIsString
STAssertFalse(Underscore.isString([[NSObject alloc] init]), @"Returns false for NSObject");
}

- (void)testCompare
{
STAssertEquals(Underscore.compare(@"a", @"b"), NSOrderedAscending, @"Can compare correctly");
STAssertEquals(Underscore.compare(@"a", @"a"), NSOrderedSame, @"Can compare correctly");
STAssertEquals(Underscore.compare(@"b", @"a"), NSOrderedDescending, @"Can compare correctly");

STAssertThrows(Underscore.compare(@{}, @{}),
@"Comparing objects that don't respond to compare: throws an exception");
}

@end
72 changes: 46 additions & 26 deletions UnderscoreTests/USArrayTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ @implementation USArrayTest

- (void)setUp
{
emptyArray = [NSArray array];
singleObject = [NSArray arrayWithObject:@"foo"];
threeObjects = [NSArray arrayWithObjects:@"foo", @"bar", @"baz", nil];
emptyArray = @[];
singleObject = @[ @"foo" ];
threeObjects = @[ @"foo", @"bar", @"baz" ];
}

- (void)testFirst
Expand Down Expand Up @@ -74,7 +74,7 @@ - (void)testHead
emptyArray,
@"Returns an empty array for an empty array");

NSArray *subrange = [NSArray arrayWithObjects:@"foo", @"bar", nil];
NSArray *subrange = @[ @"foo", @"bar" ];
STAssertEqualObjects(_.head(threeObjects, 2),
subrange,
@"Returns multiple elements if available");
Expand All @@ -94,7 +94,7 @@ - (void)testTail
emptyArray,
@"Returns an empty array for an empty array");

NSArray *subrange = [NSArray arrayWithObjects:@"bar", @"baz", nil];
NSArray *subrange = @[ @"bar", @"baz" ];
STAssertEqualObjects(_.tail(threeObjects, 2),
subrange,
@"Returns multiple elements if available");
Expand Down Expand Up @@ -134,8 +134,8 @@ - (void)testFlatten
threeObjects,
@"Returns a copy for arrays not containing other arrays");

NSArray *complicated = [NSArray arrayWithObjects:@"foo", threeObjects, nil];
NSArray *flattened = [NSArray arrayWithObjects:@"foo", @"foo", @"bar", @"baz", nil];
NSArray *complicated = @[ @"foo", threeObjects ];
NSArray *flattened = @[ @"foo", @"foo", @"bar", @"baz" ];
STAssertEqualObjects(_.flatten(complicated),
flattened,
@"Returns a flattened array when needed");
Expand All @@ -158,7 +158,7 @@ - (void)testWithout
emptyArray,
@"Removing the same array returns an empty array");

NSArray *subrange = [NSArray arrayWithObjects:@"bar", @"baz", nil];
NSArray *subrange = @[ @"bar", @"baz" ];
STAssertEqualObjects(_.without(threeObjects, singleObject),
subrange,
@"Removing one object returns the rest");
Expand All @@ -181,7 +181,7 @@ - (void)testShuffle

NSMutableArray *array = [NSMutableArray array];
for (NSUInteger i = 1; i < 100; i++) {
[array addObject:[NSNumber numberWithUnsignedInteger:i]];
[array addObject:@(i)];
}

STAssertFalse([_.shuffle(array) isEqualToArray:array],
Expand Down Expand Up @@ -317,7 +317,7 @@ - (void)testMap
emptyArray,
@"Returning nil in the map block removes the object pair");

NSArray *capitalized = [NSArray arrayWithObjects:@"Foo", @"Bar", @"Baz", nil];
NSArray *capitalized = @[ @"Foo", @"Bar", @"Baz" ];
NSArray *result = _.arrayMap(threeObjects, capitalize);

STAssertEqualObjects(capitalized,
Expand All @@ -338,10 +338,7 @@ - (void)testPluck
emptyArray,
@"Can handle empty arrays");

NSArray *lengths = [NSArray arrayWithObjects:[NSNumber numberWithInt:3],
[NSNumber numberWithInt:3],
[NSNumber numberWithInt:3],
nil];
NSArray *lengths = @[ @3, @3, @3 ];

STAssertEqualObjects(_.pluck(threeObjects, @"length"),
lengths,
Expand All @@ -360,25 +357,31 @@ - (void)testUniq
emptyArray,
@"Can handle empty arrays");

NSArray *samesObjects = [NSArray arrayWithObjects:[NSNumber numberWithInt:3],
[NSNumber numberWithInt:3],
[NSNumber numberWithInt:3],
nil];
NSArray *sameObjects = @[ @3, @3, @3 ];

STAssertEquals(_.uniq(threeObjects).count,
(NSUInteger)3,
@"Can extract 3 unique values");
STAssertEquals(_.uniq(samesObjects).count,
(NSUInteger)1,
@"Can extract 1 unique value");
(NSUInteger)3,
@"Can extract 3 unique values");

STAssertEquals(_.uniq(sameObjects).count,
(NSUInteger)1,
@"Can extract 1 unique value");

NSArray *ordered = @[ @1, @2, @2, @3, @3, @3, @4, @4 ];

NSArray *oneToFour = @[ @1, @2, @3, @4 ];

STAssertEqualObjects(_.uniq(ordered),
oneToFour,
@"Preserves order");

USAssertEqualObjects(_.uniq(emptyArray),
_.array(emptyArray).uniq.unwrap);

USAssertEqualObjects(_.uniq(threeObjects),
_.array(threeObjects).uniq.unwrap);
USAssertEqualObjects(_.uniq(samesObjects),
_.array(samesObjects).uniq.unwrap);
USAssertEqualObjects(_.uniq(sameObjects),
_.array(sameObjects).uniq.unwrap);
}


Expand Down Expand Up @@ -424,7 +427,7 @@ - (void)testFilter
threeObjects,
@"Can keep all objects");

NSArray *subrange = [NSArray arrayWithObjects:@"bar", @"baz", nil];
NSArray *subrange = @[ @"bar", @"baz" ];

STAssertEqualObjects(_.filter(threeObjects, startsWithB),
subrange,
Expand Down Expand Up @@ -528,4 +531,21 @@ - (void)testAny
_.array(threeObjects).any(_.isNumber));
}

- (void)testSort
{
NSArray *notSorted = @[ @3, @1, @2 ];
NSArray *sorted = @[ @1, @2, @3 ];

UnderscoreSortBlock numericalSort = ^(NSNumber *a, NSNumber *b) {
return [a compare:b];
};

STAssertEqualObjects(_.sort(notSorted, numericalSort),
sorted,
@"Can sort elements");

USAssertEqualObjects(_.sort(notSorted, numericalSort),
_.array(notSorted).sort(numericalSort).unwrap);
}

@end
Loading