Skip to content

Instantly share code, notes, and snippets.

@landonf
Created August 27, 2009 16:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save landonf/176421 to your computer and use it in GitHub Desktop.
Save landonf/176421 to your computer and use it in GitHub Desktop.
Lazy sequences/streams using blocks
/**
* 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);
}];
}
//
// 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
//
// 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