public
Last active

EXTNull

  • Download Gist
EXTNull.h
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
/**
EXTNull
Experimental
EXTNull is a subclass of NSNull that acts more like nil.
Calling unrecognized methods on EXTNull *will not* throw
a NSInvalidArgumentException but again return EXTNull.
You can redefine `EXTNull` to `Null` if you like clean-looking
code (just insert #define EXTNULL_SHORTHAND in your prefix file).
@example
[Null dasherized] ~> Null
@example
[@[@"A", Null, @"C"] map:method(lowercased)] ~> @[@"a", Null, @"c"];
(`lowercased` returns a copy of self with lowercased strings)
(`method()` makes a block out of a method – an equivalent of & operator in ruby)
@example
[@[@"a", Null, @"c"] compacted] ~> @[@"a", @"c"]
(compacted returns a copy of self with NSNull values removed)
 
Beware of passing EXTNull as an argument; the method would
need to support this. See [NSObject ext_pure] for how to avoid this.
@example
id string = Null;
[@"life" appendString:string] ~> Exception, since Null is not a NSString
[self gooutwith:string] ~> Exception, since Null is not a Person
@see RACTuple from ReactiveCocoa
@see the Maybe monad (http://bit.ly/data-maybe) as a possible replacement
@see license and updates at https://gist.github.com/mbixby/5125879
*/
 
#define EXTNull ((id)[_EXTNull null])
 
/**
Changes nil to EXTNull
@example
id unknown = nil;
@[maybe(unknown), maybe(@"")] ~> @[Null, @""];
@example
id one, id two = nil, @"two"
[@[maybe(one), maybe(two)] joinedBy:@" "] ~> @"two" (instead of @" two")
(joinedBy is implemented as [[array compacted] componentsJoinedByString:...])
(compacted returns a copy of self with NSNull values removed)
@see [NSObject pure], the reverse of maybe()
*/
#define ext_maybe(OBJECT) ((id)(OBJECT ?: EXTNull))
 
 
@interface _EXTNull : NSObject
 
+ (instancetype)null;
 
@end
 
 
@interface NSNull (EXTNullAdditions)
 
- (instancetype)ext_pure;
 
@end
 
 
@interface NSObject (EXTNullAdditions)
 
/**
Returns YES if self isn't nil or NSNull or EXTNull
@example
id value = Null;
!!value ~> YES
[value isNotNull] ~> NO
*/
- (BOOL)ext_isNotNull;
 
/**
Returns the underlying value of the object.
For most objects, it returns self.
EXTNull overrides this method to return nil.
@example
Null.pure ~> nil
@"".pure ~> @""
*/
- (instancetype)ext_pure;
 
@end
 
 
#ifdef EXTNULL_SHORTHAND
 
#define Null EXTNull
#define maybe ext_maybe
 
@interface NSObject (EXTNullShorthandAdditions)
- (BOOL)isNotNull;
- (instancetype)pure;
@end
 
#endif
EXTNull.m
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
#import "EXTNull.h"
 
/**
@see license and updates at https://gist.github.com/mbixby/5125879
*/
 
@implementation _EXTNull
 
+ (instancetype)null
{
static dispatch_once_t once;
static id null;
dispatch_once(&once, ^{
null = [self new];
});
return null;
}
 
// Overrides 'ext_pure' from NSObject+EXTNullAdditions
- (instancetype)ext_pure
{
return nil;
}
 
- (BOOL)respondsToSelector:(SEL)sel
{
return YES;
}
 
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
return [super methodSignatureForSelector:sel]
?: [super methodSignatureForSelector:@selector(ext_pure)];
}
 
- (void)forwardInvocation:(NSInvocation *)invocation
{
id null = self;
[invocation setReturnValue:&null];
}
 
- (instancetype)returnNull
{
return self;
}
 
- (BOOL)isKindOfClass:(Class)aClass
{
return [aClass isSubclassOfClass:NSNull.class]
|| [super isKindOfClass:aClass];
}
 
- (BOOL)isMemberOfClass:(Class)aClass
{
return [aClass isSubclassOfClass:NSNull.class]
|| [super isMemberOfClass:aClass];
}
 
@end
 
 
@implementation NSNull (EXTNullAdditions)
 
// Overrides 'ext_pure' from NSObject+EXTNullAdditions
- (instancetype)ext_pure
{
return nil;
}
 
@end
 
 
@implementation NSObject (EXTNullAdditions)
 
- (BOOL)ext_isNotNull
{
return self.ext_pure;
}
 
- (instancetype)ext_pure
{
return self;
}
 
@end
 
 
#ifdef EXTNULL_SHORTHAND
 
@implementation NSObject (EXTNullShorthandAdditions)
 
- (BOOL)isNotNull
{
return self.ext_isNotNull;
}
 
- (instancetype)pure
{
return self.ext_pure;
}
 
@end
 
#endif

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.