From oleg Thu Sep 7 10:27:59 CDT 1995 Newsgroups: comp.sys.mac.programmer.tools,comp.sys.mac.programmer.misc Subject: local procedures and natural iterators in C++ [absurd example] Summary: Snippet from grayimage_classlib showing off "nested" C++ functions Organization: University of North Texas, Denton Keywords: nested functions, iterators, closures, C++, Offscreen image Status: OR In my previous post on this newsgroup I yelled a whole paragraph about the virtues of natural iterators in grayimage_classlib and "nested" functions in C++, but failed to show a single bit of code to back those claims up. That was clearly an oversight, and I'd like to fix it now. Unfortunately, the bits of the code example patch seem to outnumber those of the original message :-(. Sorry about the long post. By "nested" functions I mean local procedures, " small, special purpose procedures that can be embedded inside another procedure. They're neat, clean, and don't clutter your interface". The quote I lifted from MacTech was from a guy who claims that the local functions are the only thing he misses about ObjectPascal. Well, a similar nesting is possible in C++, as it turns out. "Natural" iterators are those that iterate upon you, rather than you upon them. Kind of like a function one passes to qsort(): you only need to deal with the _current_ elements you're _given_, and leave the rest (iteration/shuffling/termination conditions, etc) to qsort(). The same thing with PixelActions. Only you can keep some local environment while being iterated upon, without (ab)use of static variables. Of course, these iteratees are not yet full-fledged local procedures/closures as in Scheme or Dylan; nevertheless, they're _pretty_ close. The code snippet below is taken from the working code, a Mac release of grayimage_classlib. It's the implementation of an IMAGE method that displays a grayscale image in a window (using an offscreen buffer for drawing). As hard as it is to take my word for it, it was _not_ my intention to make the code that weird: well, some stuff just happens. But it works, and in a sense, _really_ shows off "nesting" of C++ methods, to the point of absurdity, as some would probably say. Anyway, one can start counting nesting levels and matching braces... void IMAGE::display(const char * title) const { struct ImageWindow : public OffScreenWindow { ImageWindow(IMAGE& image, const char * title) : OffScreenWindow((ScreenRect)image,title,40) // 40 is Gray CLUT id { // Move pixels from IMAGE to a off-screen pixmap // Note that the rows of pixmap may be padded, by // as much as off_to_next_row bytes. So we need // to skip over the padding as we move pixels row // by row class ImageToPixMap : public PixelPrimAction { PixMapHandle pixmap; char * pixp; const card height, width, off_to_next_row; card curr_row, curr_col; void operation(GRAY& pixel) // put a pixel to pixmap[row,col] { *pixp++ = pixel; if( ++curr_col >= width ) curr_col = 0, curr_row++, pixp += off_to_next_row; } public: ImageToPixMap(OffScreenWindow& window) : pixmap(window.get_pixmap()), height(window.height()), width(window.width()), off_to_next_row(window.bytes_per_row()-window.width()), curr_row(0), curr_col(0) { assert( LockPixels(pixmap) ); pixp = GetPixBaseAddr(pixmap); } ~ImageToPixMap(void) { assert( curr_row == height && curr_col == 0 ); UnlockPixels(pixmap); pixmap = 0; } }; image.apply(ImageToPixMap(*this)); } }; ImageWindow image_window(*this,title); image_window.handle(); } This was only a single function, btw. The full code the snippet was taken from was submitted to info-mac