In SML, the following is possible for modelling lazy programming,
// Have a datatype to wrap a computation
datatype 'a susp = Susp of (unit -> 'a)
// A function to hold the computation
fun delay(f ) = Susp(f)
I know that closures can be written using Blocks,
int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
return num * multiplier;
};
So I think I can use it as a function argument. The next step would be how to use functions with no real arguments ( unit value e.g. in SML fn () =>
) and creating lazy datatypes as the one above.
Is this possible or should I be pursuing a different more obvious way ?
The end goal would be to emulate the suspended computation behaviour from SML,
let val x = Susp(fn () => horribleComp(345))
in
force(x) + force(x)
end
where force(x) is
fun force (Susp(f)) = f ()
Cool question!
You could implement a 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
That's a lot of boilerplate, but whatever. Then, you could use it like this:
id x = [Susp withBlock:^{ return someComputation(); }];
id result = [[x force] plus:[x force]];
// assuming the result of your computation has -plus:
But that's all rather silly, since for what you're doing, you really don't need another data type. Just use blocks as your datatype:
typedef id (^SuspVal)(void);
SuspVal x = ^{ return complicatedThing; };
id result = [x() plus:x()];
That's a much more compact, idiomatic way of going about it, and it's what I suggest. Unless you need to add further semantics to your lazy objects that go beyond the basic utilities of blocks, you shouldn't wrap them needlessly.
Cheers!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With