Created
August 27, 2009 16:53
-
-
Save landonf/176421 to your computer and use it in GitHub Desktop.
Lazy sequences/streams using blocks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Return a block that computes the next value and returns the next stream instance. | |
*/ | |
static PLStreamRemainingBlock NextStream (NSNumber *current) { | |
/** Create a block which will return the next stream value */ | |
PLStreamRemainingBlock f = ^{ | |
PLStreamRemainingBlock remaining; | |
NSNumber *value; | |
/* Create the new stream */ | |
value = [NSNumber numberWithInt: [current intValue] + 1]; | |
remaining = NextStream(value); | |
return [PLStream streamWithObject: value remaining: remaining]; | |
}; | |
return (PLStreamRemainingBlock) [[f copy] autorelease]; | |
} | |
- (void) countLazily { | |
NSNumber *initial = [NSNumber numberWithInt: 1]; | |
PLStream *seq = [PLStream streamWithObject: initial remaining: NextStream(initial)]; | |
[seq do: ^(id value) { | |
NSLog(@"Got lazily computed value: %@", value); | |
}]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// PLSequence.h | |
// CollectionBlocks | |
// | |
// Created by Landon Fuller on 8/25/09. | |
// Copyright 2009 Plausible Labs Cooperative, Inc.. All rights reserved. | |
// | |
#import <Foundation/Foundation.h> | |
@class PLStream; | |
typedef void (^PLBasicBlock)(); | |
typedef PLStream *(^PLStreamRemainingBlock)(); | |
@interface PLStream : NSObject { | |
@private | |
/** Initial stream value. */ | |
id _value; | |
/** Fetch remaining values. May be nil. */ | |
PLStreamRemainingBlock _remaining; | |
} | |
+ (PLStream *) streamWithObject: (id) object; | |
+ (PLStream *) streamWithObject: (id) object remaining: (PLStreamRemainingBlock) f; | |
- (id) initWithObject: (id) object remaining: (PLStreamRemainingBlock) f; | |
- (void) do: (PLBasicBlock) block; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// PLSequence.m | |
// CollectionBlocks | |
// | |
// Created by Landon Fuller on 8/25/09. | |
// Copyright 2009 Plausible Labs Cooperative, Inc.. All rights reserved. | |
// | |
#import "PLSequence.h" | |
static PLStream *PLStreamEmpty; | |
@implementation PLStream | |
+ (void) initialize { | |
if ([self class] != [PLStream class]) | |
return; | |
/* Create the empty stream */ | |
PLStreamEmpty = [PLStream streamWithObject: nil]; | |
} | |
/** | |
* Return an empty stream. | |
*/ | |
+ (PLStream *) empty { | |
return PLStreamEmpty; | |
} | |
+ (PLStream *) streamWithObject: (id) object { | |
return [self streamWithObject: object remaining: nil]; | |
} | |
+ (PLStream *) streamWithObject: (id) object remaining: (PLStreamRemainingBlock) f { | |
return [[[self alloc] initWithObject: object remaining: [[f copy] autorelease]] autorelease]; | |
} | |
- (id) initWithObject: (id) object remaining: (PLStreamRemainingBlock) f { | |
if ((self = [super init]) == nil) | |
return nil; | |
_value = [object retain]; | |
_remaining = [f copy]; | |
return self; | |
} | |
- (void) dealloc { | |
[_remaining release]; | |
[_value release]; | |
[super dealloc]; | |
} | |
static void withPool (void (^block)()) { | |
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
block(); | |
[pool release]; | |
} | |
// from PLSeq protocol | |
- (void) do: (PLBasicBlock) block { | |
/* Nothing to do */ | |
if (!_value) | |
return; | |
__block PLStream *stream = [self retain]; | |
while (stream->_value != nil) { | |
withPool(^{ | |
block(stream->_value); | |
if (!stream->_remaining) { | |
stream = nil; | |
} else { | |
PLStream *new = stream->_remaining(); | |
[stream release]; | |
stream = [new retain]; | |
} | |
}); | |
} | |
[stream release]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment