Skip to content

Instantly share code, notes, and snippets.

@iamleeg
Last active December 23, 2015 23:59
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iamleeg/6713330 to your computer and use it in GitHub Desktop.
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.
#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]);
}
}
}
#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]);
}
}
}
@iamleeg
Copy link
Author

iamleeg commented Sep 26, 2013

The second, only marginally less over-engineered solution was suggested by David Ronnqvist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment