Cool question!
You can implement the lazy container in Objective-C as follows (but you probably shouldn't, see below):
typedef id (^SuspBlock)(void); @interface Susp : NSObjecti - (id)initWithBlock:(SuspBlock)block; + (id)withBlock:(SuspBlock)block; - (id)force; @end // ----- @interface Susp () @property (nonatomic, copy) SuspBlock _block; @end @implementation Susp @synthesize _block; - (id)initWithBlock:(SuspBlock)block { self = [super init]; if (self != nil) { self._block = block; } return self } + (id)withBlock:(SuspBlock)block { return [[[self alloc] initWithBlock:bloc] autorelease]; } - (id)force { return self._block(); } - (void)dealloc { self._block = nil; [super dealloc]; } @end
These are many templates, but anything. Then you can use it as follows:
id x = [Susp withBlock:^{ return someComputation(); }]; id result = [[x force] plus:[x force]];
But all this is pretty stupid, because for what you do, you really don't need another data type. Just use blocks as a data type:
typedef id (^SuspVal)(void); SuspVal x = ^{ return complicatedThing; }; id result = [x() plus:x()];
This is a much more compact, idiomatic way to get around this, and this is what I suggest. Unless you need to add additional semantics to your lazy objects that go beyond the basic block utilities, you don't need to wrap them unnecessarily.
Hurrah!
source share