Lazy datatypes in Objective C

In SML for modeling lazy programming, the following is possible:

// 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 an argument to a function. The next step is to use functions without real arguments ( the unit value , for example, in SML fn () => ) and create lazy data types, as described above,

Is this possible, or should I follow another more obvious path?

The ultimate goal would be to emulate the suspended behavior of calculations from SML,

 let val x = Susp(fn () => horribleComp(345)) in force(x) + force(x) end 

where the force (x) is equal

 fun force (Susp(f)) = f () 
+6
source share
1 answer

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]]; // assuming the result of your computation has -plus: 

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!

+5
source

Source: https://habr.com/ru/post/887651/


All Articles