Block(BlockForeach)


The BlockForeach category adds an iterative method to Blocks that repeatedly runs the block as long as it produces non-nil output, then runs another block with that output.

Extends Class: Block
Declared In: BlockForeach.h



Methods

-foreach:

foreach:


- (void) foreach:(Block*)iterator;
Discussion

Repeatedly runs the receiver block (using the value method), each time executing the iterator block with the receiver's output. The output of iterator is discarded. The receiver block will be executed until it returns nil, at which point foreach: will finish, without executing iterator a final time.

This method can be used to produce loops that repeatedly call a function that produces data, such as the FSFile readln method, and returns nil when it is done. The following block of Perl code is a common idiom for iterating over all the lines in a file; it takes advantage of the fact that Perl's angle-bracket operator returns undef when there is no data left in a file:

open FILE, '<', "......";
while (<FILE>) {
 chomp;
 doSomething($_);
}


In F-Script, the readln method of FSFile returns nil when the file has been completely read, so we can create a very similar loop:

file2 := FSFile open:'....'.
[ file readln ] foreach:[ :line |
 "No 'chomp' necessary - readln cuts off the newline for us"
 obj doSomething:line.
].


A more F-Script-like alternative approach would be to use the readlines method, then run the block over the entire array:

file2 := FSFile open:'....'.
[ :line | obj doSomething:line. ] value: @ (file2 readlines).


However, with this code, readlines will read in the entire file at once, which may be very inefficient if the file is large. The iterative method using foreach, on the other hand, only reads and stores a single line at a time.

© Andrew Weinrich Last Updated: Wednesday, October 15, 2008