Last active
December 23, 2015 23:59
-
-
Save iamleeg/6713330 to your computer and use it in GitHub Desktop.
You probably don't need to tell me that this is a bad idea.
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
#import <Foundation/Foundation.h> | |
typedef NS_ENUM(int, GJLRangeDirection) { | |
GJLRangeDirectionPositive, | |
GJLRangeDirectionNegative, | |
}; | |
@interface GJLRange : NSEnumerator | |
+ (instancetype)rangeWithStart: (NSNumber *)start end: (NSNumber *)end step: (NSNumber *)step; | |
@end | |
@implementation GJLRange | |
{ | |
double _start; | |
double _end; | |
double _step; | |
double _cursor; | |
GJLRangeDirection _direction; | |
} | |
+ (instancetype)rangeWithStart: (NSNumber *)start end: (NSNumber *)end step: (NSNumber *)step | |
{ | |
NSParameterAssert(start != end); | |
NSParameterAssert(step != 0); | |
GJLRange *range = [self new]; | |
range->_start = [start doubleValue]; | |
range->_end = [end doubleValue]; | |
range->_step = [step doubleValue]; | |
if ([step compare:@0] == NSOrderedAscending) { | |
range->_direction = GJLRangeDirectionNegative; | |
NSParameterAssert(range->_start > range->_end); | |
} else { | |
range->_direction = GJLRangeDirectionPositive; | |
NSParameterAssert(range->_start < range->_end); | |
} | |
range->_cursor = range->_start; | |
return range; | |
} | |
- (BOOL)isStillGoing | |
{ | |
switch (_direction) { | |
case GJLRangeDirectionPositive: | |
return _cursor - _end < _step; | |
case GJLRangeDirectionNegative: | |
return _cursor - _end > _step; | |
} | |
} | |
- (id)nextObject | |
{ | |
if (![self isStillGoing]) { | |
return nil; | |
} | |
NSNumber *result = @(_cursor); | |
_cursor += _step; | |
return result; | |
} | |
@end | |
@interface NSNumber (GJLRange) | |
- (id <NSFastEnumeration>)to:(NSNumber *)destination by:(NSNumber *)step; | |
- (id <NSFastEnumeration>)to:(NSNumber *)destination; | |
@end | |
@implementation NSNumber (GJLRange) | |
- (id <NSFastEnumeration>)to:(NSNumber *)destination by:(NSNumber *)step | |
{ | |
return [GJLRange rangeWithStart: self end: destination step: step]; | |
} | |
- (id <NSFastEnumeration>)to:(NSNumber *)destination | |
{ | |
return [self to:destination by: ([self compare:destination] == NSOrderedAscending)?@1:@(-1)]; | |
} | |
@end | |
int main(int argc, const char * argv[]) | |
{ | |
@autoreleasepool { | |
for (id bottleCount in [@10 to: @1]) { | |
printf("%d green bottles, hanging on the wall...\n", [bottleCount intValue]); | |
} | |
} | |
} |
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
#import <Foundation/Foundation.h> | |
typedef NS_ENUM(int, GJLRangeDirection) { | |
GJLRangeDirectionPositive, | |
GJLRangeDirectionNegative, | |
}; | |
@interface GJLRange : NSEnumerator | |
+ (instancetype)rangeWithStart: (NSNumber *)start end: (NSNumber *)end step: (NSNumber *)step; | |
@end | |
@implementation GJLRange | |
{ | |
double _start; | |
double _end; | |
double _step; | |
int _index; | |
GJLRangeDirection _direction; | |
} | |
+ (instancetype)rangeWithStart: (NSNumber *)start end: (NSNumber *)end step: (NSNumber *)step | |
{ | |
NSParameterAssert(start != end); | |
NSParameterAssert(step != 0); | |
GJLRange *range = [self new]; | |
range->_start = [start doubleValue]; | |
range->_end = [end doubleValue]; | |
range->_step = [step doubleValue]; | |
if ([step compare:@0] == NSOrderedAscending) { | |
range->_direction = GJLRangeDirectionNegative; | |
NSParameterAssert(range->_start > range->_end); | |
} else { | |
range->_direction = GJLRangeDirectionPositive; | |
NSParameterAssert(range->_start < range->_end); | |
} | |
return range; | |
} | |
- (id)objectAtIndexedSubscript:(NSUInteger)index | |
{ | |
return @(_start + (_index * _step)); | |
} | |
- (BOOL)isStillGoing:(NSNumber *)currentValue | |
{ | |
switch (_direction) { | |
case GJLRangeDirectionPositive: | |
return [currentValue doubleValue] - _end < _step; | |
case GJLRangeDirectionNegative: | |
return [currentValue doubleValue] - _end > _step; | |
} | |
} | |
- (id)nextObject | |
{ | |
NSNumber *result = self[_index]; | |
if (![self isStillGoing:result]) { | |
return nil; | |
} | |
_index += 1; | |
return result; | |
} | |
@end | |
@interface NSNumber (GJLRange) | |
- (id <NSFastEnumeration>)to:(NSNumber *)destination by:(NSNumber *)step; | |
- (id <NSFastEnumeration>)to:(NSNumber *)destination; | |
@end | |
@implementation NSNumber (GJLRange) | |
- (id <NSFastEnumeration>)to:(NSNumber *)destination by:(NSNumber *)step | |
{ | |
return [GJLRange rangeWithStart: self end: destination step: step]; | |
} | |
- (id <NSFastEnumeration>)to:(NSNumber *)destination | |
{ | |
return [self to:destination by: ([self compare:destination] == NSOrderedAscending)?@1:@(-1)]; | |
} | |
@end | |
int main(int argc, const char * argv[]) | |
{ | |
@autoreleasepool { | |
for (id bottleCount in [@10 to: @1]) { | |
printf("%d green bottles, hanging on the wall...\n", [bottleCount intValue]); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The second, only marginally less over-engineered solution was suggested by David Ronnqvist.