Hey arithma, I like your implementation, it's generic enough and easy to extend by creating new state structs and iterator functions.
I decided to copy your approach in Objective-C, I also made it extra hard for myself by compiling it with GCC without Foundation.
lazyThing.h contains the basic definitions for the lazy thing we're implementing.
#import <objc/Object.h>
@class LazyThing;
@protocol IterFunc
- (id) iterate:(id) state;
@end
@interface GenNext : Object {
id _state;
id <IterFunc> _iterFunc;
}
- (id) initWithState:(id) state iterFunc:(id <IterFunc>) iterFunc;
- (LazyThing *) apply;
@end
@interface LazyThing : Object {
id _state;
GenNext *_genNext;
LazyThing *_next;
}
- (id) initWithState:(id) state iterFunc:(id <IterFunc>) iterFunc;
- (id) stateAtIndex:(int) index;
@end
lazyList.m is our implementation:
#import "lazyThing.h"
@implementation GenNext : Object
- (id) initWithState:(id) state iterFunc:(id <IterFunc>) iterFunc {
self = [super init];
if (self) {
_state = state;
_iterFunc = iterFunc;
}
return self;
}
- (LazyThing *) apply {
return [[LazyThing alloc]
initWithState: [_iterFunc iterate: _state]
iterFunc: _iterFunc];
}
@end
@implementation LazyThing : Object
- (id) initWithState:(id) state iterFunc:(id <IterFunc>) iterFunc {
self = [super init];
if (self) {
_state = state;
_genNext = [[GenNext alloc]
initWithState: _state
iterFunc: iterFunc];
_next = nil;
}
return self;
}
- (id) stateAtIndex:(int) index {
if (index == 0) {
return _state;
}
if (_next == nil) {
_next = [_genNext apply];
}
return [_next stateAtIndex: --index];
}
- free {
if (_state) {
[_state free];
}
if (_genNext) {
[_genNext free];
}
if (_next) {
[_next free];
}
}
@end
Some definitions for our Fibonacci state:
@interface FibState : Object {
int _m;
int _n;
}
- (id) initWithM:(int) m n:(int) n;
- (int) m;
- (int) n;
@end
@implementation FibState : Object
- (id) initWithM:(int) m n:(int) n {
self = [super init];
if (self) {
_m = m;
_n = n;
}
return self;
}
- (int) m {
return _m;
}
- (int) n {
return _n;
}
@end
@interface FibIterFunc : Object <IterFunc>
- (id) iterate:(id) state;
@end
@implementation FibIterFunc
- (id) iterate:(id) state {
FibState *fstate = (FibState *)state;
return [[FibState alloc]
initWithM: [fstate n]
n: [fstate m] + [fstate n]];
}
@end
And finally, main.m:
int main(void) {
FibState *zeroth = [[FibState alloc] initWithM: 0 n: 1];
FibIterFunc *iter = [[FibIterFunc alloc] init];
LazyThing *fibs = [[LazyThing alloc]
initWithState: zeroth
iterFunc: iter];
FibState *eighth = [fibs stateAtIndex: 8];
printf("%d\n", [eighth m]);
[fibs free];
[iter free];
return 0;
}
And yes, that IS manual memory management. :)
This code works, I didn't use blocks or any modern features so clearly it's not idiomatic Objective-C, I also sort of winged the memory management, it's probably broken.