Jump to content

  • Log In with Google      Sign In   
  • Create Account

In Which Christopher Robin Buys Some Cheese

C# was designed to not implement the SGL

Posted by , 05 October 2006 - - - - - - · 227 views

That's the conclusion I've reached. After jumping through dozens of hoops to finally get everything to a point where it pretty much works as you'd expect, they light one of the hoops on fire and put it over a shark tank. And the sharks have fricken lazers on their fricken heads.

Basically, as my recent post in the .Net forum has mentioned, I've discovered you can't apply operator++ to unnamed temporaries. I don't know if that's the proper word for it or not, but essentially it means ++container.Begin() is invalid. This mostly makes sense, but it doesn't seem like something that would be impossible to overcome. Just create an unnamed temporary that is immediately discarded, no big deal.

That wouldn't be quite so big a deal except for this: the C# compiler isn't smart enough to know that its against the rules. Instead, it spits out invalid code that, at run time, throws a nasty exception. The situation is slightly better if Begin is a read-only property instead of a function --- then, the compiler crashes when it sees the code. So at least you know in advance something is wrong, rather than silently emitting invalid code, even if a compiler error would be more appropriate.

So what, exactly, does this mean for the SGL? Well, it could well mean that I'm done. Things like for(Iterator i = ++vec.Begin(); i != vec.End(); ++i) are not exactly uncommon in my code. I certainly can't imagine a more straight forward way of skipping the first element in a container. Technically, I could use vec.Begin().Advance(1), but that's ugly. Seriously, I can't stand it; my test code is littered with it, and every time I write a loop I die a little inside.

And more importantly, the compiler won't stop me, or anybody else, from using the first form. It'll just happily spit out invalid code that'll cause the program to choke when executed. That's unacceptable.

Perhaps I should buckle down and learn C++/CLI. Perhaps, since that is perfectly valid C++ code, it will also be perfectly valid C++/CLI code. And the whole project will be saved. I doubt it, though. I'm a little too tired to be optimistic at this stage.


Survey says: Ignore it

Posted by , 19 September 2006 - - - - - - · 125 views

Conceptually, what is the difference between a Sequence and a Sorted Container? Answer: The fact that you specify the order of a sequence, while the sorted container decides on its own where to put things. Its a bit of a simplification, but overall I think that really sums it up.

With that in mind, having Insert(i, x) being defined for a Sorted Container simply doesn't make sense. More importantly, expecting a function that relies on Insert(i, x) to work properly on both Sequences and Sorted Containers doesn't make sense.

So, this is the final breakdown I have decided on:

Container -> ErasableContainer -> ISequence -> IRandomAccessSequence
-> IBackSequence
-> IFrontSequence
-> ISortedContainer

Unfortunately, this makes for a system that is rather verbose. List, for instance, is an ErasableContainer, an ISequence, an IBackSequence, and an IFrontSequence all at once. Vector is slightly better, being an ErasableContainer, an IRandomAccessSequence, and an IBackSequence. Stack would simply be a Container, but it would accept an IBackSequence as a parameter.

This is what I meant when I said a couple posts back that the hardest part of working with Containers is figuring out what to inherit from. At some point, I would like to sit down and see if I can't come up with something a little less clunky by dropping the STL association. But I doubt I will.

Once I have actually finished making these changes [they aren't substantially different from what I had originally], I think I'll go ahead and publish a version 0.1. I'll be leaving out all the SortedContainers, because they're in a rather broken state, but I do have both List and Vector, as well as quite a few standard algorithms. So there's still plenty to laugh at.

Until next time.


On containers

Posted by , 12 September 2006 - - - - - - · 222 views

When designing my iterators, I pretty much just went to the C++ standard [chapter 24, Section 1: Iterator Requirements], and copied it. That worked great, the end results were quite pleasing.

Initially, I did the same thing with the containers. In fact, I did the same thing with containers before I even did it with iterators. However, I now realize this was rather silly. There's a lot of duplication in the definitions of sequences and associative containers. For instance, the only Sequence methods that aren't also in Associative Containers are insert(p, n, t) and insert(p, i, j) [erase(q) and erase(q1, q2) are present in both, but have different return values ... I must admit I don't understand why].

Theoretically, this isn't that big a deal; you can just duplicate the definitions. This is exactly what I did initially. However, then generic algorithms can't work on both Sequences and Associative Containers except via iterators, even if they are restricted to the common interface. See, for instance, insert_iterator. In C++ that works with both types, but C# requires a common type that defines the insert(p, i) method.

So should that common type exist? If so, should it do all of the common methods?

What I'm leaning towards now is inserting a ModifiableContainer type between Container and Sequence/Associative Container. Right now, Container is pretty much read only, and I figure that's a pretty useful distinction to have. So adding a second layer with the inserts and erases makes sense to me. But then I wonder if the extra complexity is justified, and if I shouldn't just put it all into the base Container type. Or maybe even make it completely orthogonal...right now I have a BackInsertSequence type that defines PushBack, PopBack, and Back; why not have an InsertSequence type that defines Insert and Erase?

Bah, explicit type constraints are making this a lot harder than it needs to be [sad] It was so much nicer when I could let the C++ standards committee do my design for me. Now I'm going to have to sit down and draw out exactly what I want everything to be capable of, and what I don't want them to be capable of, and go from there. Uber boring.


Generic cycling

Posted by , 07 September 2006 - - - - - - · 229 views

In the wake of the untimely demise of my car, I've lost my will to do much of anything other than play Baldur's Gate, a game I find entertaining but ultimately rather klunky and poorly executed. Being without a television, however, its all I've got to satisfy my need for some role playing action.

I've been feeling the itch to code, however, and so I'm going to give a quick update on the SGL in the hopes that it'll push me over the edge and I'll start back up again.

It turns out that learning generics at the same time as designing a complicated series of generic containers wasn't that good an idea. The whole equality issue I encountered is a prime example of why: I did it right initially, but a misunderstanding in how generics work resulted in my replacing my correct Equals functions with incorrect versions that still did the job. I later corrected my misunderstanding, but the incorrect Equals remained. Later attempts to perform trickery then failed, because Equals wasn't implemented right, and I concluded that such trickery was impossible when in reality it was quite trivial to fix.

All told, creating those writeups last week were a god send. They made me realize how shoddy my initial design was, and I have since cleaned it up quite a bit. The actual use of the iterators remains largely unchanged, but now you can do this:

void function<T, Itr>(RandomAccessIterator<T, Itr> begin, RandomAccessIterator<T, Itr> end)
where Itr : RandomAccessIterator<T, Itr>
//Some algorithm specialized for RandomAccessIterators

void function<T, Itr>(BidirectionalIterator<T, Itr> begin, RandomAccessIterator<T, Itr> end)
where Itr : BidirectionalIterator<T, Itr>
//Same algorithm, but using the more generic BidirectionalIterator

By doing this, I have also made it possible for the compiler to infer all the type arguments on its own. To see why, consider what the functions would have been before:

void function<T, Itr>(Itr begin, Itr end)
where Itr : BidirectionalIterator<T, Itr>
//All I can do is use the Bidirectional version, no random access optimizations :(

In both versions, the function has two generic parameters, T and Itr. When infering those parameters, the compiler only looks at the actual function arguments...it doesn't consider the where clauses. In the second version, T is only present in the where clause, so the compiler has to be told explicitly what type to subsitute in. Now that I can specify the specific type of iterator directly [rather than delegating it to the where clause], that is no longer an issue.

The other change this has made possible is the addition of iterator adaptors. For instance, I now have a BackInsertIterator that mimics the behavior of std::back_insert_iterator. How it works will have to wait for another day, though, since I haven't gotten to the chapter on generic containers.

Why not? Because when I went to write up that section, I realized my containers were a horrible mess. I wrote them first, so that I had something to iterate over, but the radical changes to my iterator design only propagated backwards so far as was neccessary to keep things compiling properly. The end result was a nightmare, with a horrible hodgepodge of classes and interfaces and general crap that needs to be gotten rid of.

If this post does the trick, it should only take a day or so to get right. Then we can continue our discussion of the SGL.

In the mean time, I need to figure out some way to get snazzy screenshots out of this project so that my journal is a little less boring.


*edit: PS, I've implemented a bunch of the generic algorithms required by the C++ standard. I'm rather proud of the fact that I can actually copy the code from an actual implementation, fix the stylistic differences [* -> Value, in particular], and end up with a fully working function. I don't, of course, because that would be stealing, and most of them are near impossible to read anyhow. But the fact that I could makes me feel all proud of my little generic iterators.

Happy Panda (Part Two)

Posted by , 27 August 2006 - - - - - - · 150 views

First of all, if you at all enjoyed Super Troopers, go see Beerfest right now. I have never in my life heard an entire theater laughing uncontrollably at the same time until this movie. I have heard individual people laugh, and had the occasional "ha ha ha ha done" laugh pass through the croud, but this was full force "I can't breath" laughter. This movie is awesome enough that it could share some of the funny with Club Dread and end up with two good movies afterwards.

So, when last we met, I had given you an overview of some of the high level decisions I had made. In the interim, snk_kid was kind enough to point out just how pointless this project really is: Dinkumware is working on STL/CLR, and it will be included with VS at some point in the near future. But that's OK. I'll bet I'll have SGL finished first, so when I'm done I'll forward them a copy for inspiration [wink]

Today, I would like to get down into the nitty gritty details of how everything actually works up to this point.

We will begin with iterators, because they were the hard part. The C++ iterator library defines five classes of iterators:

RandomAccess -> Bidirectional -> Forward -> Input
-> Output

All iterators support forward movement via operator++, so you can consider enumerations to be a form of InputIterator1. I have chosen to follow suit, and make use of the same heirarchy. I somewhat regret not making OutputIterator independant of the basic chain, but fixing that now would be non-trivial.

In C++, this heirarchy is largely imagined...you specify what type of iterator you are using the iterator_category tag, but otherwise a BidirectionalIterator is simply one that defines operator-- in addition to operator++. In C#, such behavior would not work...generic types and methods depend on inheritance to see what behavior is and is not allowed. For this reason, I define six types:

  • interface InputIterator -- specifies a read-only property Value

  • interface OutputIterator -- specifies a write-only property Value

  • abstract class Iterator -- Implements operator++, Advance, and Distance in terms of the abstract method Increment(), and implements operator== in terms of Equals.

  • abstract class ForwardIterator -- Derives from Iterator, InputIterator, and OutputIterator. Provides no additional functionality, and leaves the Value property abstract.

  • abstract class BidirectionalIterator -- Adds an abstract method Decrement, and implements operator-- in terms of it. Also adds support for using operator- in place of Distance2, and overrides the default Advance to allow for negative values of n.

  • abstract class RandomAccessIterator -- Adds an abstract indexer (essentially operator[]) that allows constant time movement of the iterator. Implements operator+ and operator- (when used with integral operands) and overrides the default Advance to make use of the indexer.

Now, lets say you are implementing an iterator for an iterator for a List class [err..LinkedList class...damn .Net calling arrays lists [flaming]]. In this case, you would want to inherit from BidirectionalIterator. In order to get all the functionality of a BidirectionalIterator you only have to provide five functions: self equality via Equals, the Value property, Increment, and Decrement. That's it...everything else you need is provided transparently by the underlying classes. If you were implementing Vector.Iterator, you would inherit from RandomAccessIterator, and provide the same functions, plus the indexer.

So what about using them? That's just as straight forward. Just decide what type of iterator you are working with, and go from there. As an example, here's a hypothetical implementation of for_each:

delegate void Function<T>(T v);
void for_each<T, Itr>(Itr begin, Itr end, Function<T> f)
where Itr : Iterator<T>, InputIterator<T>
for(; begin != end; ++begin)

//Later, within some function:
List<int> l;
for_each<int, List.Iterator>(l.Begin(), l.End(), delegate(int v) {System.Console.Write("{0} ", v);});

If you implementing Sort, which requires RandomAccessIterators, then you would simply replace the where line above with where Itr : RandomAccessIterator<T>, and you'd be free to use begin[5] or end[-10].

Now, as I mentioned, there is a rather significant problem with the overview I just gave. Namely, overloaded operators don't work that way. In .Net, overloaded operators are static functions...this means you can't inherit them, and the return value is permanantly stuck with one type. You would not think this would be a problem, because even if dealing with a base class the virtual functions would still call the proper methods. And indeed, I am now entirely unable to recreate the bugs I encountered at the time.3 However, the combination of inheritance, generics, and overloaded operators resulted in some subtle bugs, especially with regards to equality. Sometimes, they could be gotten around with simple casts to the proper type, but not always.

The solution I found was the Curiously Recurring Generic. Observe:

class Iterator<T> {
public static Iterator<T> operator++() {/*implement me*/}

class VectorIterator<T> : Iterator<T> {}


class Iterator<T, Itr> where Itr : Iterator<T, Itr> {
public static Itr operator++() {/*implement me*/}

class VectorIterator<T> : Iterator<T, VectorIterator<T>> {}

Now, all the operators operate on the derived class instead of on the base class, even though the operator itself is defined in the base class. It is really quite slick, I think.

This recurence goes all the way up, with ForwardIterator, BidirectionalIterator and RandomAccessIterator all accepting the same second parameter. Only InputIterator and OutputIterator, which only define a property that doesn't care about the actual iterator in any way, are exempt.

This is not without its pitfalls, of course. In addition to making the definition of iterators slightly more complex, it seriously hinders the ability of the compiler to infer types automatically. You have to parameterize based on iterator, because you can not have a BidirectionIterator, for example, on its own. If it isn't obvious why, try it out:

void SomeFunc<T>(BidirectionalIterator<T, BidirectionalIterator<T, BidirectionalIterator<T, ...

void SomeFunc<T, Itr>(Itr iterator) where Itr : BidirectionalIterator<T, Itr>

C# does not look at the constraints list when infering parameters, so it has no way of knowing what type to assign to T. This means you have to specify it every time:

SomeFunc<int, List<int>.Iterator>(l.Begin());

As you might imagine, that gets annoying rather quickly. I have identified two ways to help it along. The first is for when I'm lazy:

void SomeFunc<T, Itr>(Itr iterator, T placeholder)

The placeholder is just there to put T into the argument list so that C# can figure things out on its own. Obviously, this is not an ideal solution. The alternative is much cleaner:

static class Algorithms<T> {
void SomeFunc<Itr>(Itr iterator) where Itr : BidirectionalIterator<T, Itr> {}

//later, to use it:

You still have to specify T, but that is typically fairly straight forward. It is the Itr parameter that you don't want to be bothered with. So while still not ideal, it is at least marginally easier to work with.4

I think that pretty much brings us up to speed on Iterators. Unfortunately, I got distracted a few times and now I have to work in an hour, so Containers will have to wait. They are pretty straight forward, however, and there are no real complications with their use.

The last thing I'd like to do is show how one can use iterators in practice. Namely, I'm going to show off the code that allows an iterator range to be used in a foreach structure. I stripped the comments, because they were in the XML format MS likes, and that made it a bit verbose for such a simple structure. I added a few where neccessary.

public class RangeEnumerator<T, U>
: IEnumerator<T>, IEnumerable<T>
where U : Iterator<T, U>, InputIterator<T, U>
public RangeEnumerator(U begin_, U end_) {
begin = begin_;
end = end_;

IEnumerator<T> IEnumerable<T>.GetEnumerator() {
return this;

public System.Collections.IEnumerator GetEnumerator() {
return this;

public bool MoveNext() {
//Enumerations start one before the begining of the range, so itr
// itr being null signifies that position.
if(itr == null) {
itr = (U)begin.Clone();
return itr != end;
return itr != end;

public T Current {
get {
if(itr == null || itr == end)
throw new InvalidOperationException();
return itr.Value;

Object System.Collections.IEnumerator.Current {
get {
//Is it possible to somehow use the other form of Current for
// this? I should probably yank both bodies into a separate
// function.
if(itr == null || itr == end)
throw new InvalidOperationException();
return (Object)itr.Value;

public void Reset() {
itr = null;

// I don't know what this function is for, but I get yelled at if it
// isn't here.
public void Dispose() {

private U itr;
private U begin;
private U end;

//This is a helper class that allows the compiler to infer the two type
// parameters. It occurs to me now that I could possibly move
// RangeEnumerator into this class and simplify things a bit.
public static class Range<T>
public static RangeEnumerator<T, U> Create<U>(U begin, U end)
where U : Iterator<T, U>, InputIterator<T, U> {

return new RangeEnumerator<T, U>(begin, end);

This is how you actually use them:

class Program
public static void Main(string[] args) {
//I know we haven't covered vectors yet, but I'm use you can figure out what this does :)
Vector<int> v = new Vector<int>();
for(int i = 0; i < 10; i++)

foreach(int i in new RangeEnumerator<int, Vector<int>.Iterator>(v.Begin(), v.End()))

//Or, more simply:
foreach(int i in Range<int>.Create(v.Begin(), v.End()))

//Although it is not the point of the code, you can also do this:
foreach(int i in v)

As an aside, when I finished typing out that demo program I pressed <ctrl><shift>B.

And with that, I bid you fare well.


1This is a bit of a simplification...you are only allowed to read from an input iterator once [this restriction is lifted by ForwardIterator], but you can reset an enumerator and pass through it multiple times if you like.

2I have to look through my notes to see if there's a reason why this functionality is provided by BidirectionalIterator and not by Iterator itself...the actual implementation is simply rhs.Distance(lhs), so there's no reason why it wouldn't work with ForwardIterators as well.

3The fact that I can't recreate the bugs, despite them being quite obvious at the time, bothers me. This calls into question all the decisions I have made since. I think over the next couple days I will try and work backwards and recreate the problems I had before. Hopefully, it wasn't just a misunderstanding that I have since rectified. I fully understood the source of the problems at the time, but I was learning a lot at the time so you never know.

4There is a third option I just now tried out:

void SomeFunc<T, Itr>(BidirectionalIterator<T, Itr> iterator) where Itr : BidirectionalIterator<T, Itr> {}

In that case, it infers both parameters just fine. However, equality doesn't work right. As I mentioned before, equality is the area that was most severely affected by the issues that lead to implementing the recusion in the first place. I know exactly how to fix it, and I'm willing to bet that doing so will lead me to remember what caused the bugs in the first place. So that is where I shall begin my search.

Happy Panda

Posted by , 25 August 2006 - - - - - - · 209 views

Windows is back. Hooray! It was even easier than I thought it would be...I envisioned losing all my data and having to reinstall all my software, but all it took was putting in the new harddrive, loading it with the ghost I made before things went up in smoke, and performing a repair installation of Windows.

So now I'm back to work on Super Awesome Library 5000. Or possibly STL.Net. Or maybe SGL. I haven't decided yet. Its pretty close to being at a point where I would feel comfortable showing off actual code, but not quite. I think I'm going to finish up with the basic algorithms and maybe implement a deque, and then release a demo version before I do any hard work on the sorted containers [although I have a basic Set class put together, it is pretty ugly and doesn't quite work yet].

In the mean time, I'm going to give a basic overview of the project as a whole, and some of the design decisions I've made along the way.

First of all, let me make it clear that this was a project born of boredom. Neccessity may be the mother of invention, but boredom is the drunk uncle that nobody really likes. It basically started because I was a little annoyed that enumerators in .Net don't allow you to modify the values you are enumerating. I missed my iterators, but realized that given the behavior of .Net generics iterators wouldn't work anyhow. But then one day I got bored [my internet broke down so I couldn't play WoW, and I have no television] and decided that I would go ahead and try to implement iterators anyhow. I knew I would fail, but I had nothing better to do with my time.

As luck would have it, I succeeded. Or somewhat succeeded...it was rudimentary, but a good proof of concept. My internet was still down, so I figured what the hell...why not just go all the way and recreate the whole shebang? Now, its evolved into something I want to do just because I can.

The reason I say all that is because I'm still convincing myself that its OK to reinvent the wheel in this case [embarrass] I'm fully expecting the end result to be slower than the standard counterparts, as well as harder to use in some regards, and probably less safe to boot. And I know it isn't portable as of yet, because mono is incapable of running it [although gmcs does compile it all properly]. But maybe I'll learn something useful1, or people will find it handy. At the very least, I'll have something to chug away at while I'm bored [grin]

So, onto the actual design. To begin with, let me explain where it isn't going to be a straight port, and why.

The biggest difference is that I've decided to omit custom allocators. From a design standpoint, they seem to go against the idea of running in a managed environment. From a practical standpoint, I wouldn't know how to program a custom allocator in .Net anyhow. Also, .Net doesn't allow you to specify default parameters, so you would have to explicitly state that you wanted the standard allocator every single time. This fact is compounded by MSs decision to not implement typedefs in C#, so even that shorthand isn't possible in the language I chose to implement this system in. All together, the decision to remove custom allocators was a pretty easy one to make.

A similar process will probably result in sorted containers not being parameterized on comparators. As I mentioned, I haven't actually completed this portion of things yet, but I will almost certainly go the route of System.Collections.Generic.SortedDictionary, and accept a Comparer object. I haven't quite finished analyzing what effects this will have, however, so the final result remains to be seen.

I am also discarding the SC++L style of using_lots_of_underscores in favor of a more .Net-friendly UsingLotsOfCapitalization.

Iterators are an actual concrete type rather than the abstract pseudo-type they are in C++. In addition to allowing Iterators to work at all within the confines of .Net generics, they allowed me to make Distance and Advance member functions rather than global functions. This is quite important, as I'm pretty sure its the only way functions like std::lower_bound can perform better with vectors than they do with lists. It is impossible to specialize generics, so there can only be one implementation of Advance(itr, n), which would have to be to the effect of while(n--) itr++;. But, itr.Advance(n) can be inherited by a RandomAccessIterator to be just itr += n;2

For obvious reasons, iterators aren't dereferenced via *itr. Instead, a property Value is exposed.

There are no iterator tags, or type-traits, or anything like that, because generics would be completely unable to utilize them. Instead, such information is carried in the inheritance. If you are implementing a BidirectionalIterator, then you inherit from BidirectionalIterator. I suppose that isn't entirely accurate...you can use inheritance in C++ to achieve similar effects, but you don't *have* to. distance_type is always int, and you just have to keep track of value_type on your own3.

Although they do not now, ultimately the containers will all expose .Net-style interfaces. Vector will inherit from IList, and so forth. The primary reason they don't already is because I'm lazy. I'm also torn on whether or not to rename List so it is a little less confusing when mingled in with the standard containers. I suppose naming it LinkedList wouldn't be *that* bad, but that can wait. They do currently inherit from IEnumerable [and its generic cousin] so they can be used with foreach.

I think that pretty much covers the big changes that I'm aware of. Although I used a lot of words to describe them, they're largely superficial and don't really effect how you actually use everything. Implementations are a little odd, but that's something I have to worry about, not you [grin] The weirdness, however, all comes from inheriting from the proper objects. Once you've done that, all the grunt work is done, and you just have to provide three or four implementations so that all the real hard stuff [like overloaded operators, which were a bitch and a half to get working right] is done for you automagically.

I want to move onto implementation details, but I have to work in two hours and honestly, I'm not sure I have the time. Its pretty complex, and I'd rather not just throw the stuff out there without explaining why I did what I had to do. So that can wait for another day.


1 Speaking of learning something, did you know that _ is a valid name in C#? I assume it works in other languages as well, I've just never bothered to try it and see. I'm tempted to write a class named _ and fill it with functions named __ and ___ and ____ just for the hell of it. Unfortunately, this knowledge was learned independant of STL.Net, so I haven't quite justified my time yet.

2 In my last journal entry, I stated the following:

The biggest hurdle I think I have left to overcome is how to specialize algorithms for specific types of iterators. Haven't had any inspirations on that front in a while, so I fear it might not happen.

This was only partially true, and was mostly my memory playing tricks on me. I haven't had any inspirations as to how to specialize algorithms...instead, I think making Distance and Advance member functions has allowed me to work around the problem to a certain extent. I forgot about that. It isn't a perfect solution, but its good enough for government work.

3 The lack of a way to specify value_type is, to date, the biggest annoyance I have with this whole system. I say that only half-heartedly, however, as I'm not positive a simple typedef would actually solve any of the problems I associate with the lack of said typedef. It is a conventient scapegoat, though.

Sad Panda

Posted by , 12 August 2006 - - - - - - · 105 views

A while back I got bored and decided to develop a CLR compliant version of the C++ standard containers library in C#. In particular, I wanted to see if I could get iterators working. So far, my success has been rather promising. I've got Vector and List working, with a rudimentary Set implementation, and my experiments with generic algorithms have proven mostly successful. The biggest hurdle I think I have left to overcome is how to specialize algorithms for specific types of iterators. Haven't had any inspirations on that front in a while, so I fear it might not happen.

However, then my harddrive died, and I got pushed onto my secondary harddrive, which is occupied by Linux. This itself doesn't really bother me. I dislike working on the Dark Side, but Ubuntu is relatively painless, so I just run with it. Eventually, I'll find my missing XP CD and everythign will start coming up Milhouse again.

In the meantime, I caught mono, and spent a fair amount of time figuring out how to work with the 2.0 compiler. Unfortunately, Monodevelop does not support compiling with gmcs, so I'm stuck with make. Again, not that big a deal. I figured it all out, set my project directories up in a nice tidy way, and compiled my test program. It compiled flawlessly, without so much as a warning. I then run the resulting executable.

First, I get a warning: "Implement me." Then, I get an error: "Code should not be reached. Aborting...aborted."

Superb. Apparently, mono's generic support is not quite at 100%, and my [admitedly complicated] use of them falls in the part still left to be finished. Which means I can develop my code, but not test it.



The death and return of Conner McCloud

Posted by , 13 July 2006 - - - - - - · 124 views

Life is certainly strange. Some fourteen months ago, I was graduating from a respected university with two sought after degrees. Today, I am posting from a library [twelve minutes left on this session, I had better hurry], preparing for my next shift at a local Dairy Queen.

And I honestly do not remember when I was last happier.

It isn't so much that I enjoy being an assistant manager at Dairy Queen. Although, I do. Very much so. It is more that I have a vision again. A new goal for my life after the last faded years ago to the turmoil of earning those two degrees.

But I am getting ahead of myself, and I am down to eight and a half minutes. No time for dillies, and less time for dallies.

As I said, some fourteen months ago I graduated. I immediately began searching for employment, both with software firms [my first degree being in Computer Science], and with engineering firms [my second degree being in Electical Engineering]. I found employment difficult to find. As the months wore on, I realized the reason employers did not find me attractive was that I myself had little to no desire to work in either field. I love developing software, and I love developing hardware, and I especially love the magical realm where the two disciplines meet. But I simply could not envision myself doing it for a living. They are a hobby to me. A hobby I love, and will always love, but a hobby none the less. Not a career.

But what else could I do? I have, after all, nearly killed myself getting through college, not to mention putting myself rather seriously in debt, all to enter the very fields I was not discarding. I was distraught. It was not a happy couple of weeks as I searched my soul for some sign of what I should do.

Fortune and I have a very healthy relationship, and in this case it did not let me down. At the very same time I was was going through this dilemma, my brother was having trouble with Algebra, and attending study sessions with his teacher and a bunch of other students over the summer. As I was currently unemployed, I volunteered to help out in my spare time. The experience was, for lack of a better word, breathtaking. I felt satisfaction watching those kids grasp math that I never felt writing programs or building robots. It was a satisfaction that I have only felt in passing here on Gamedev, pretending I know enough about programming to help others in the General Programming forum.

It became immediately clear what I am meant to do. Teach. I've heard the jokes from my peers; those who can't, and so forth. I don't really care. This is what will make me happy, I am more certain of that then anything I've ever felt before.

And so I am returning to school. Apparently, to teach high school math requires actual coursework. Not much, of course, since I already have a degree in math. Just a handful of courses in education. And some reading and writing bull shit that the School of Mines never saw fit to officially teach me. I figure I could knock it out in a year, maybe three semesters, if I felt so inclined. But I've done the full time student thing, and I think I want to take a break from it. What's the hurry? I have my entire life ahead of me, and now that I have a goal I can enjoy myself for a while.

And yes, make ice cream for ten dollars an hour. Sure, its not the $40k a year job I was told to look forward to when I left highschool, but it is honest work, I get experience with Teenagers, and five nights a week I get a free meal. Really, what more could a guy want?

And so there you all have it. The quick and dirty summary of where Conner McCloud is. I am sure you have all been dying for an update on my amazing life, and I am more than happy to oblige. And for those of you living in the greater Denver area, feel free to swing by my store. I promise I'll give the brasier guy a stern talking to should he spit in your meal.

Recent Entries

Recent Comments