Hack Jam Log Book is a log of progress made in and around a weekly hack session. Topics include natural language processing, high energy electronics, linguistics, interface design, &c. Enjoy.

Recent Posts:

Archives:

18.7.12

 

annual update

I have been working with C++ quite a bit lately and had to deal with things like this:

template < class List_entry>
void List< List_entry>::traverse(void (*visit)(List_entry &))
{
   Node *q;

   for (q = head; q; q = q->next)
      (*visit)(q->entry);
}

It was useful to invoke this method when I needed to print the contents of the list. I just passed in the name of a function like this:

void print_entry ( List_entry &e )
{
   std::cout << e << std::endl;
}

I thought I could do a bit more advanced things by adding a void* argument, but there would be a little bit of work with that and it was not perfectly general.

The notion of lambdas also occurred to me but I did not think too hard about it since they are still new in C++ so I was like ... meh.

Then I kept thinking some more and I was like, uggh, the way I toss bits around, an additional arbitrary callback argument will be approximately as powerful as a temporary anonymous function, if not as syntactically pretty, and both of these are going to be more or less limited to doing only so much with the current object in the iteration.

The potential versatility suggested by this kind of element-iterator with arbitary callback suggests interesting possibilities that, well, ought to be a lot easier! It would be great if I could call traverse on a binary search tree and have it generate a dot file representing the relationships between nodes so a computer program could draw them nicely for me. In fact that kind of thing seems like what any traverse method worth its salt ought to have been meant for. But it's unpleasant to do in a general way and without unnecessarily abusing global state! A callback with three parameters (parent, left, right) is one option, but I don't want to be bound to the number 3. Maybe I can just do (a, b, NULL) for a two-parameter version. But why stop there? How about vararg? Or maybe a vector of arguments? These all seem very unsatisfying and ad-hoc to me!

It might be nice if some portion of the current stack frame could be made available to my callback function -- even in a safe and read-only way. I promise I do not want to break things, just know where I'm at so I can figure out where I'm going! Oughtn't there be a concise way to define a callback with read access to certain local variables belonging to the function invoking the callback?

How can I achieve such a thing in C or C++? I mulled over this for several days, toying in my head with various unimplementable thoughts and vacillating over whether the idea itself was good or not, or whether I was already overlooking any useful language feature that made this easy as cake, or whether I had dug myself into a tarpit of hopelessly unimprovable design? A binary search tree could be drawn any number of ways, but, darnit, why not with such a traverse method as described above? No world can be a happy one that has factories where one robot tosses doodads onto a conveyor belt and another operates a claw to inspect each, one by one, without knowing anything of the status or history or progress of the doodad-loading operation; else that claw-bearing robot be an uninterestingly simple one, and the factory incapable of producing anything of value.

I was completely flummoxed. This is so basic a need, and it tears at the fabric of my thoughts with such relentlessness, someone else must already have figured it out; I must rest my mind a short time before I drive myself crazier!

Though I may have permitted my brain a brief respite from the harrowing, I could not fully abandon the matter, in spite of the mounting practical reasons to do so. Before I was prepared to abandon all responsibility and set forth once more and finally forever down this path to ultimate insanity, the notion was abruptly thrust into my consciousness to consider the bigger picture. Bigger than binary trees -- what of the general class of graphs? Here, my mind began to spin again. It would not cut it to just pass references to the parent, left, and right nodes. Total parameter variability was necessary to account for the diversity of graph representations and characteristics! In the same instant that it occurred to me that the entire state of the invoking function must be fully accessible to the callback, a sharp blow glanced off my lower abdomen and I landed on my back, striking my head on the asphalt. Dizzy, I wheezed through a scowl and by the time I had lifted my head up, a formation of one thousand diiqs and calcnerds had begun rapidly marching towards me, brandishing brightly colored pugil sticks. A dark horse with a confident gait followed. It was the general, Adam. The head of each of the two advancing columns set down his weapon and appeared on either of my shoulders. They leaned in close to my ears as if to whisper. I could not fret over the decision to listen to one or the other because they both shouted in unison, startling me further. My mind was blank from fear and as I groped for comprehension, they boxed my ears and while I reeled they fluttered up in front of me and mocked me with gestures I could barely make out through the taste of tears and snot. They flew off into the sunset together, the army marching along under them. Parentheses formed in their wake, and I could not tell if they were opening or closing.

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]