tag:blogger.com,1999:blog-68009344464578987932008-08-18T20:37:15.985-04:00MoserwareJeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.comBlogger31125tag:blogger.com,1999:blog-6800934446457898793.post-62374091054829691352008-07-31T07:34:00.001-04:002008-07-31T07:37:28.035-04:00Building an Object-Oriented Parasitic Metalanguage<p>It's all about pattern matching. The rest is just details. </p><p>My <a href="http://www.moserware.com/2008/06/ometa-who-what-when-where-why.html" target="_blank">last post on OMeta#</a> focused on what it is and the vision I have for its future. Briefly, <a href="http://www.cs.ucla.edu/~awarth/ometa/" target="_blank">OMeta</a> is a new language that makes it easier to design programming languages in an <a href="http://en.wikipedia.org/wiki/Object_oriented" target="_blank">object-oriented</a> fashion using very few lines of quite readable code. <a href="http://www.codeplex.com/ometasharp" target="_blank">OMeta#</a> is my attempt to support OMeta on the <a href="http://en.wikipedia.org/wiki/Common_Language_Runtime" target="_blank">.NET runtime</a>. My main strategy has been to base its design off of <a href="http://www.cs.ucla.edu/~awarth/" target="_blank">Alessandro Warth</a>'s JavaScript implementation of <a href="http://jarrett.cs.ucla.edu/ometa-js/" target="_blank">OMeta/JS</a>. This post gets into the specifics of how I've done this so far, but my hope is that you might see some places where the design could use improvement and that you might be encouraged to leave a comment so that it could get better.</p><p><strong>High Level Design</strong></p><p>At its core, OMeta has a very simple design. The highest level of abstraction is a grammar. Here is a calculator grammar in the current implementation of OMeta#:</p><pre style="font-family:consolas, courier new, courier, monospace;"><span style="color:#0000ff;">ometa</span> <span style="color:#2b91af;">Calculator</span> <: <span style="color:#2b91af;">Parser</span> {<br /> Digit = Super((Digit)):d -> { d.ToDigit() },<br /> Number = Number:n Digit:d -> { n.As<<span style="color:#0000ff;">int</span>>() * 10 + d.As<<span style="color:#0000ff;">int</span>>() }<br /> Digit,<br /> AddExpr = AddExpr:x '+' MulExpr:y -> { x.As<<span style="color:#0000ff;">int</span>>() + y.As<<span style="color:#0000ff;">int</span>>() }<br /> AddExpr:x '-' MulExpr:y -> { x.As<<span style="color:#0000ff;">int</span>>() - y.As<<span style="color:#0000ff;">int</span>>() }<br /> MulExpr,<br /> MulExpr = MulExpr:x '*' PrimExpr:y -> { x.As<<span style="color:#0000ff;">int</span>>() * y.As<<span style="color:#0000ff;">int</span>>() }<br /> MulExpr:x '/' PrimExpr:y -> { x.As<<span style="color:#0000ff;">int</span>>() / y.As<<span style="color:#0000ff;">int</span>>() }<br /> PrimExpr,<br /> PrimExpr = '(' Expr:x ')' -> { x }<br /> Number,<br /> Expr = AddExpr<br />} </pre><p>A grammar is composed of rules (which are sometimes referred to as "productions"). Both the grammar itself and the rules have the same form:</p><p><a href="http://bp1.blogger.com/_Zfbv3mHcYrc/SIkraxIzsvI/AAAAAAAAA0k/5GqUY3WfhEk/s1600-h/ruleapplication.png" target="_blank"><img src="http://bp1.blogger.com/_Zfbv3mHcYrc/SIkraxIzsvI/AAAAAAAAA0k/5GqUY3WfhEk/s400/ruleapplication.png" /></a> </p><p>Going into the rule is a list of things of the <em>input</em> type (here they're represented by red circles) and coming out on the right is a list of things of the <em>destination</em> type (represented by purple triangles). As you can see from the diagram, the output list can have lists inside of it. In the calculator grammar, the circles are individual characters and the output is a single integer. </p><p><strong>My "<a href="http://en.wikipedia.org/wiki/Greenspun" target="_blank">Ad Hoc, Informally-Specified, Bug-Ridden, Slow Implementation of Half of Common Lisp</a>"</strong></p><p>As an implementer of OMeta, you have to make several design choices. One of the first is how to represent grammars. Since OMeta is object-oriented, I decided that it made sense to represent grammars as a .NET class (a.k.a. "<a href="http://msdn.microsoft.com/en-us/library/system.type.aspx" target="_blank">Type</a>"). Grammars contain rules; the obvious choice for implementing rules is to use a <a href="http://msdn.microsoft.com/en-us/library/ms173114.aspx" target="_blank">method</a>. This especially makes sense because rules can refer to rules in their base grammar. For example, the above calculator grammar has a rule called "Digit" which captures a single <em>numeric</em> digit. The "Digit" rule applies the "Digit" rule in its base grammar (Parser) that simply captures a digit <em>character</em>. It does this by applying the special "Super" rule which will use the base grammar to apply the rule that is specified by an argument. Since rules are implemented as methods and rules can "override" their definition from their base grammar, it made sense to make rule methods "<a href="http://msdn.microsoft.com/en-us/library/aa645767(VS.90).aspx" target="_blank">virtual</a>."</p><p>Another important decision is how to represent data going into and out of a rule application. An easy choice is to represent the data in a <a href="http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx" target="_blank">List<T></a>. This works out well except for the small detail that lists can contain other lists. This nested list idea has been around for at least 50 years in <a href="http://en.wikipedia.org/wiki/Lisp_(programming_language)" target="_blank">LISP</a> and languages derived from it (like <a href="http://en.wikipedia.org/wiki/Scheme_(programming_language)" target="_blank">Scheme</a>). Since it has worked out fairly well in those languages, I <a href="http://www.youtube.com/watch?v=J0UjU0rtavE" target="_blank">stole</a> the idea of a LISP-like list in my <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264656&changeSetId=15493" target="_blank">OMetaList<TInput></a> class which is a list of other lists with a special case that makes lists of length 1 equivalent to the element itself.</p><p>These decisions get us started, but a problem comes up if you try to implement the <a href="http://en.wikipedia.org/wiki/Factorial" target="_blank">factorial</a> function using recursion in an OMeta grammar:</p><pre><span style="color:#0000ff;">ometa</span> <span style="color:#2b91af;">Factorial</span> {<br /> Fact 0 -> { 1 },<br /> Fact :n ?(n.As<<span style="color:#0000ff;">int</span>>() > 0) Fact((n.As<<span style="color:#0000ff;">int</span>>() - 1)):m -> { n.As<<span style="color:#0000ff;">int</span>>() * m.As<<span style="color:#0000ff;">int</span>>() }<br />} </pre><p>If you look carefully at this grammar, you'll see that it only says two things:</p><ol><li>If the next element of input matches a 0, return 1 </li><li>If the next element of input is something greater than zero, store its value to "n" and then apply the "Fact" rule supplying it with the value of "n - 1" and capture that result to "m". Finally, return "n * m". </li><br /></ol><p>What might not be obvious at first is that any time you store something to a variable using an expression like ":n", the value stored must be of the destination type (e.g. a triangle in the diagram). This makes us need to update our mental model for how OMeta works. We need a place to store rule "arguments" which are already in the destination type. </p><p>One way of doing this is to create an argument stack that is separate from the rest of the input. Additionally, we'll need a place to store grammar-local variables as well as a place to remember previous results of rule applications for performance reasons. This gives us a much more complete picture of what really occurs:</p><p><a href="http://bp0.blogger.com/_Zfbv3mHcYrc/SIsm-B67IgI/AAAAAAAAA1g/Ody7RBndMGg/s1600-h/rullapplicationfromstack.png" target="_blank"><img src="http://bp0.blogger.com/_Zfbv3mHcYrc/SIsm-B67IgI/AAAAAAAAA1g/Ody7RBndMGg/s400/rullapplicationfromstack.png" /></a> </p><p>When a rule needs to consume input, it will first attempt to grab pop an item from the argument stack. If the stack is empty, then next element from the input list can be read. </p><p>I decided to store all of these details into a single class which I call an <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264658&changeSetId=15493" target="_blank">OMetaStream<TInput></a> which internally uses an <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264656&changeSetId=15493" target="_blank">OMetaList<TInput></a> for input data and an OMetaList<<a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=316963&changeSetId=15493" target="_blank">HostExpression</a>> for storing the argument stack. The arguments are actually stored in an <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=314607&changeSetId=15493" target="_blank">OMetaProxyStream<TInput></a> which inherits from <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264658&changeSetId=15493" target="_blank">OMetaStream<TInput></a>, but this is just an implementation detail.</p><p>With the major data structures out of the way, one important choice remaining is how to handle going down the wrong path. If you look at the calculator grammar, you'll see that the "AddExpr" rule can be of the form "x + y", <strong>or</strong> "x - y", <strong>or</strong> a "MulExpr".</p><p>How does OMeta know which one to take? It makes a <em>prioritized choice</em> by trying each of the alternatives in the order specified. If it discovers that it has gone down the wrong path (e.g. the next item from the input is a "-" instead of a "+"), it needs to backtrack and reset itself to the condition it was in before the bad choice and then try the next option. </p><p>There are two obvious ways of doing this. The first approach is to leverage runtime support by using exceptions. This is exactly what OMeta/JS does. Using exceptions has an advantage of making the generated code simpler because there is no explicit code to "unwind the stack" in case you go down a bad path. </p><p>Although it makes the code easier to read, I decided against using exceptions and instead chose to use methods that return a boolean value to indicate if they succeeded. I did this for two important reasons:</p><ol><li>.NET does a bit of extra work when an exception is thrown (e.g. getting a stack trace). Therefore, throwing an exception has a non-trivial performance penalty. </li><li>Rules have prioritized choice. This means that failing a single choice doesn't imply that the whole rule fails. Failing can be a very common occurrence (it's not <em>exceptional</em>) and this makes it very performance sensitive. </li></ol><p>Here's a small glimpse of what the generated code looks like for attempting to apply the "AddExpr" rule:</p><pre><span style="color:#2b91af;">OMetaList</span><<span style="color:#2b91af;">HostExpression</span>> x;<br /><span style="color:#2b91af;">OMetaStream</span><<span style="color:#0000ff;">char</span>> addExprOut;<br /><br /><span style="color:#0000ff;">if</span>(!MetaRules.Apply(AddExpr, inputStream2, <span style="color:#0000ff;">out</span> x, <span style="color:#0000ff;">out</span> addExprOut))<br />{<br /> <span style="color:#0000ff;">return</span> MetaRules.Fail(<span style="color:#0000ff;">out</span> result2, <span style="color:#0000ff;">out</span> modifiedStream2);<br />}</pre><p>In this case, AddExpr is the name of the rule which is implemented as a method. Data is read from the "inputStream2" which is an OMetaStream (where the red circles are characters). The resulting list is saved to the "x" variable and the modified stream is stored in "addExprOut". In order to make back-tracking easier, OMetaStreams are mostly <a href="http://en.wikipedia.org/wiki/Immutable_object" target="_blank">immutable</a>, which means that they can't change. Instead of updating the stream itself, you get a fresh copy of the stream that contains what the result would be. If you need to back track, you can simply ignore the rule application output. As a side benefit, it makes it slightly easier to debug since you don't have to worry about the <a href="http://www.moserware.com/2007/11/attack-of-mutations-or-why-we-do-we.html" target="_blank">mutations that could otherwise occur</a>.</p><p><strong>Parasitic?</strong></p><p><a href="http://en.wikipedia.org/wiki/Image:Female_Catolaccus_grandis_wasp.jpg" target="_blank"><img src="http://bp0.blogger.com/_Zfbv3mHcYrc/SIqMacuDOXI/AAAAAAAAA1M/Gq_7xwTI9Rs/s200/Female_Catolaccus_grandis_wasp.jpg" align="right" /></a>OMeta's <a href="http://www.cs.ucla.edu/~awarth/" target="_blank">creator</a> <a href="http://vpri.org/pipermail/ometa/2008-July/000051.html" target="_blank">likes to refer to OMeta as a "parasitic language"</a> because it doesn't exist on its own. It always lives on top of a "host language." This makes an implementation usually defined in terms of its host language. That's why there is "OMeta/<strong>JS</strong>" which uses JavaScript as a host language. Although my ultimate goal for OMeta# is to have the host language be any .NET language, I decided to use C# as my first host language. </p><p>One of the first issues that came up was trying to recognize what exactly is C# code. As you can see from examples in my <a href="http://www.moserware.com/2008/06/ometa-who-what-when-where-why.html" target="_blank">last post</a>, my first attempt was to pick a really ugly pattern that wouldn't occur in normal use. I picked two consecutive @ signs as in:</p><p>@@/*This is C#*/@@</p><p>It worked out well, but it had the downside that it was, well... <em>incredibly ugly</em>. I have since written <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=328653&changeSetId=15493" target="_blank">a rudimentary C# recognizer</a> written in OMeta# itself that is aware of strings and comments. The upside is that the syntax looks a little nicer:</p><p>{ /*This is C#*/ }</p><p>Using C# as the host language had several implications. The most challenging was working with C#'s static type system. This was both a blessing and a curse. On the one hand, I had to constantly think about where the data came from and where it was going. This forced me to actually understand the overall design better. On the other hand, I had to spend <em>so much time</em> thinking about it. Late-bound systems with dynamic typing such as Smalltalk and JavaScript remove the need for people to spend so much time doing this. </p><p>I'm optimistic that over time a lot of the stronger annoyances will go away. For example, the current syntax forces type identification as in:</p><pre>-> { n.As<<span style="color:#0000ff;">int</span>>() * 10 + d.As<<span style="color:#0000ff;">int</span>>() }</pre><p>Where, OMeta/JS can just say:</p><pre>-> { n * 10 + d }</pre><p>I'm not exactly sure how to do this yet. My initial guess is that I might be able to write some sort of <a href="http://herbsutter.wordpress.com/2008/06/20/type-inference-vs-staticdynamic-typing/" target="_blank">type inference</a> algorithm (preferably written in OMeta#) that could do a reasonable job. My current ideas are tied too closely with the specific host language and would require a bit of work to port them to other host languages like Visual Basic. Another approach is to implement one or more helper classes that could enable <a href="http://en.wikipedia.org/wiki/Duck_typing" target="_blank">duck typing</a> (e.g. if it looks like a certain type, walks like that type, and quacks like the type, it's <em>probably</em> that type).</p><p>Being able to have strong static typing internally while having a very clean syntax would be ideal (e.g. sort of like the C# 3.0 "<a href="http://msdn.microsoft.com/en-us/library/bb383973.aspx" target="_blank">var</a>" keyword). Static typing is usually harder to achieve, but if you can do it well, you get many benefits. C# designer <a href="http://en.wikipedia.org/wiki/Anders_Hejlsberg" target="_blank">Anders Hejlsberg</a> said it well in a <a href="http://www.se-radio.net/podcast/2008-05/episode-97-interview-anders-hejlsberg" target="_blank">recent interview</a>:</p><blockquote><p>"I don't see a lot of downsides to static typing other than the fact that it may not be practical to put in place, <em>and it is harder to put in place</em> and therefore takes longer for us to get there with static typing, but once you <em>do</em> have static typing. I mean, gosh, you know, like hey -- the compiler is going to report the errors <em>before</em> the space shuttle flies instead of whilst it's flying, that's a good thing!" </p></blockquote><p>Another issue that came up was properly handling inheritance. It makes sense to use "virtual" methods for rules, but this also requires you to emit the "<a href="http://msdn.microsoft.com/en-us/library/ebca9ah3.aspx" target="_blank">override</a>" directive to <a href="http://msdn.microsoft.com/en-us/library/04xcc4t1.aspx" target="_blank">avoid warnings</a>. <a href="http://msdn.microsoft.com/en-us/library/ms228459.aspx" target="_blank">Another warning</a> cropped up from my use of the "<a href="http://msdn.microsoft.com/en-us/library/hfw7t1ce.aspx" target="_blank">base</a>" keyword in the many delegates that makes it convenient from a code emission perspective, but frustrating from a verifiable security perspective. Both of these warning are being left for a latter phase.</p><p>Compiler issues were only one factor. The other significant piece was aesthetics. A notable number of rules yield specific lists as their result. C# doesn't <a href="http://msdn.microsoft.com/en-us/library/bb384062.aspx" target="_blank">quite</a> have a good, clean way of expressing an OMetaList (that is, a list of lists). In order to get around this, I created the "<a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=328644&changeSetId=15493" target="_blank">Sugar</a>" helper class which makes it slightly easier to write these lists. It's still far from perfect. Instead of having a nice way for expressing lists like that OMeta/JS:</p><pre>-> ['add', x, y]</pre><p>You have to do this instead:</p><pre>-> { <span style="color:#2b91af;">Sugar</span>.Cons("add", x, y) }</pre><p>This annoyance can probably be fixed by tricking the C# recognizer to act as if C# had a nice implicit way of expressing an OMetaList and then re-writing the expression to use the Sugar class.</p><p>Beyond C#, there is the "meta" "host language" which is the .NET <a href="http://en.wikipedia.org/wiki/Common_Language_Runtime" target="_blank">common language runtime</a> itself. For code to play nice on it, it should abide by the .NET <a href="http://blogs.msdn.com/kcwalina/archive/2008/04/09/FDGDigest.aspx" target="_blank">framework design guidelines</a> which dictate naming conventions and general practices. This had a parasitic effect in that it led me to name my rules after the naming guidelines for methods (e.g. they must be <a href="http://c2.com/cgi/wiki?PascalCase" target="_blank">PascalCased</a>). Thus, in OMeta# there is the "<strong>D</strong>igit" rule instead of the "<strong>d</strong>igit" rule. OMeta/JS opts to prefix metarule method names with an underscore to make them not collide with other rules. I also wanted to hide metarules so that people would have to try harder to do the wrong thing; the best I could come up with to convey this idea was to implement them using an <a href="http://msdn.microsoft.com/en-us/library/ms173157.aspx" target="_blank">explicit interface</a> exposed via a property (e.g. instead of "_apply", I have "MetaRules.Apply").</p><p><strong>Being a Contextual Packrat</strong></p><p>The last intriguing thing about OMeta is exactly how it implements parsing. It uses a technique called a <a href="http://en.wikipedia.org/wiki/Parsing_expression_grammar" target="_blank">Parsing Expression Grammar</a> (PEG) that <a href="http://www.bford.info/" target="_blank">Bryan Ford</a> <a href="http://www.bford.info/pub/lang/peg.pdf" target="_blank">introduced</a> in 2004. It's just a fancy way to say you support the following features: (The table comes from the OMeta <a href="http://www.cs.ucla.edu/~awarth/papers/dls07.pdf" target="_blank">paper</a>. I've also included how OMeta# implements them to prove its legitimacy):</p><table cellspacing="0" cellpadding="2" border="1"><tbody><tr><td valign="top"><strong>expression</strong></td><td valign="top"><strong>meaning</strong></td><td valign="top"><strong>OMeta# Function</strong></td></tr><tr><td valign="top"><em>e</em><sub>1</sub> <em>e</em><sub>2</sub></td><td valign="top">sequencing</td><td valign="top">Seq</td><br /></tr><tr><td valign="top"><em>e</em><sub>1</sub> <em>e</em><sub>2</sub></td><td valign="top"><em>prioritized</em> choice</td><td valign="top">MetaRules.Or</td><br /></tr><tr><td valign="top"><em>e</em><sup>*</sup></td><td valign="top">zero or more repetitions</td><td valign="top">MetaRules.Many</td></tr><tr><td align="top"><em>e</em><sup>+</sup></td><td valign="top">one or more repetitions (not essential)</td><td valign="top">MetaRules.Many1</td></tr><tr><td valign="top">~<em>e</em></td><td valign="top">negation</td><td valign="top">MetaRules.Not</td></tr><tr><br /><td valign="top"><<em>p</em>></td><td valign="top">production application</td><br /><td valign="top">MetaRules.Apply</td></tr><tr><td valign="top">'x'</td><td valign="top">matches the character x</td><td valign="top">Exactly</td></tr><br /></tbody></table><br /><p>The most interesting aspect to me is the prioritized choice. This is in contrast to "<a href="http://en.wikipedia.org/wiki/Context-free_grammar" target="_blank">Context-Free Grammar</a>s" (CFGs) which are the traditional way of defining parsers. To highlight the difference, consider parsing this line of C/C++ code:</p><pre><span style="color:#0000ff;">if</span> (condition1) <span style="color:#0000ff;">if</span> (condition2) Statement1(); <span style="color:#0000ff;">else</span> Statement2();</pre><p>Is it the same as:</p><pre><span style="color:#0000ff;">if</span> (condition1)<br />{<br /> <span style="color:#0000ff;">if</span> (condition2)<br /> {<br /> Statement1();<br /> }<br /> <span style="color:#0000ff;">else</span><br /> {<br /> Statement2();<br /> }<br />}</pre><p>... or is it:</p><pre><span style="color:#0000ff;">if</span> (condition1)<br />{<br /> <span style="color:#0000ff;">if</span> (condition2)<br /> {<br /> Statement1();<br /> } <br />}<br /><span style="color:#0000ff;">else</span><br />{<br /> Statement2();<br />}</pre><p>This is the classic "<a href="http://en.wikipedia.org/wiki/Dangling_else" target="_blank">dangling else</a>" problem. Context Free Grammars usually have this problem because they are free of any context when they are parsing (surprise!). In these situations, you often have to rely on something besides the grammar itself to resolve these ambiguities. Parsing Expression Grammars don't have this type of problem because you specify explicitly which one to try first. The prioritized choice therefore avoids ambiguity. </p><p>In order to make the performance relatively in line with the size of the input, a technique of "<a href="http://en.wikipedia.org/wiki/Memoization" target="_blank">memoization</a>" is used. This means the parser remembers what it has done previously; it does this as a <a href="http://en.wikipedia.org/wiki/Space-time_tradeoff" target="_blank">space-time tradeoff</a>. Keeping all those previous values have given them the reputation of being a "<a href="http://pdos.csail.mit.edu/~baford/packrat/">packrat</a>" parser.</p><p>Let's say you have</p><pre> AddExpr = AddExpr:x '+' MulExpr:y -> { x.As<<span style="color:#0000ff;">int</span>>() + y.As<<span style="color:#0000ff;">int</span>>() }<br /> AddExpr:x '-' MulExpr:y -> { x.As<<span style="color:#0000ff;">int</span>>() - y.As<<span style="color:#0000ff;">int</span>>() }<br /> MulExpr</pre>and you try the first choice (AddExpr:x '+' MulExpr:y), but you get to where you're expecting a "+" and it isn't there. You'll notice that the second choice (AddExpr:x <strong>'-'</strong> MulExpr:y) repeats the first part (namely AddExpr:x). Instead of re-evaluating it, you can just retrieve the stored value that you remembered, or rather<em> memoized</em>.<br /><br /><p>Well, it's almost that simple. Note that the definition of an add expression (AddExpr) is <a href="http://en.wikipedia.org/wiki/Left_recursion" target="_blank">left-recursive</a>. This means that the left side is defined in terms of itself. A naïve implementation of the parser would try to evaluate "AddExpr" by applying the first choice which started with a AddExpr which would then cause it to try to apply AddExpr again and eventually cause a <a href="http://en.wikipedia.org/wiki/Stack_overflow" target="_blank">stack overflow</a>.</p><p>It's not a trivial problem to fix. In fact, the paper that introduced Parsing Expression Grammars said that left-recursion should be avoided since you can rewrite the rule to avoid left-recursion. This is unfortunate guidance because the rewritten rule sometimes loses the clarity that the left-recursive version of the rule had.</p><p>At the start of this year, a <a href="http://www.vpri.org/pdf/packrat_TR-2007-002.pdf" target="_blank">paper</a> came out showing a very clever trick that makes left recursion possible.</p><p>Say that we're parsing the expression "1+2+3" using the "AddExpr." At the start of the expression we look at our memoization table to see if we have a precomputed value for "AddExpr". Since it is our first time, we won't find anything. The first part of the trick is to immediately store the result of "Fail" as the memoized result for AddExpr when starting at offset 0. We do this <em>before</em> we attempt to apply the rule.</p><p>When the parser uses recursion and finds itself again asking for the value of "AddExpr" at position 0, it <em>will</em> find a result of "fail" and thus fail that choice. It will then continue down to "MulExpr" where it will eventually match "1". The second part of the trick is to treat this value of "1" for "AddExpr" at position 0 as a "seed parse." The parser will then attempt to "grow the seed<em>"</em> by starting over at the beginning of the input stream, but this time it will remember its previous successful match. This will cause it to match "1+2" for AddExpr and then start over again by growing the seed to finally match "1+2+3." </p><p>In hindsight, it's a very simple idea. However, I say that only after some serious debugging time where I kept finding problems in my poor implementation. Alas, the entire algorithm is implemented in only a few lines of code in the "MetaRules.Apply" function in <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264639&changeSetId=15493" target="_blank">OMetaBase.cs</a>.</p><p>So there you have it, you now know all of the interesting ideas in OMeta#. </p><p><strong>Where is This Going?</strong></p><p>OMeta# is a hobby project that's been a labor of love for me. You might have already guessed that if you noticed that <a href="http://www.codeplex.com/ometasharp/SourceControl/ListDownloadableCommits.aspx" target="_blank">most check-ins</a> occur late at night or on the weekends. It's been slow, but it's coming together. Probably the most exciting highlight in the development came when I got enough of OMeta# working that I could rewrite parts of itself in OMeta#. This has the benefit of being cool from a meta self-reproducing level, but it's also a bonus because the code becomes much more readable and introspective. For example, compare the <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=315537&changeSetId=15493" target="_blank">C# recognizer that I wrote by hand</a> to the <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=328653&changeSetId=15493" target="_blank">OMeta# grammar version</a> that implements the same idea. </p><p>This approach of writing more of OMeta# <em>in</em> OMeta# will continue. It's my hope that as much as possible will be written in itself. A significant next step would be to rewrite the <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264619&changeSetId=15493" target="_blank">code generator</a> as an OMeta# grammar. This isn't a new design idea. Each subsequent version of Smalltalk has been <a href="http://en.wikipedia.org/wiki/Bootstrapping_%28compilers%29" target="_blank">bootstrapped</a> by its previous version. </p><p>I'll be the first to point out that there are a lot of rough edges to my current implementation. If you look around the <a href="http://www.codeplex.com/ometasharp/SourceControl/ListDownloadableCommits.aspx" target="_blank">source code</a>, you'll see several comments labeled "// HACK" where I admit a hacked version of an idea. One of the most glaring problems is that debugging is annoyingly difficult. I haven't yet implemented an optimizer for the generated code which causes a lot of unnecessary metarule applications. The second annoyance is that just stepping into so many methods that fail often takes a long time. Over time, I hope to add better hints to get more traditional error messages that you get from good compilers so that you don't have to step through the generated code to debug a grammar. </p><p>As mentioned earlier, the language recognizer could use some work to make the syntax cleaner as well inferring types so that grammar writers don't have to explicitly declare them. I have confidence that the work that would go into a good C# host language implementation would directly port to other languages such as Visual Basic.</p><p>There's also a great need cross pollination with other projects such as the <a href="http://en.wikipedia.org/wiki/Dynamic_Language_Runtime" target="_blank">Dynamic Language Runtime</a> (DLR) which has already tackled some of the issues that OMeta# will face. Additionally, languages such as <a href="http://en.wikipedia.org/wiki/F_Sharp_programming_language" target="_blank">F#</a> have similar data structures already built-in that OMeta uses. <a href="http://en.wikipedia.org/wiki/Boo_(programming_language)" target="_blank">Boo</a> and <a href="http://en.wikipedia.org/wiki/Nemerle" target="_blank">Nemerle</a> have interesting extensibility points which could provide some good ideas. The problem for me is that there is so many different places to look. It'd be great if you know these languages (or others) and could tell me via a comment or better yet, by sending code of how they could help OMeta#. </p><p>As of right now, I plan on keeping the core functionality in C# rather than rewriting everything in another language or by using the DLR. The main reason is that C# is wide-spread in availability, both on .NET as well as on <a href="http://en.wikipedia.org/wiki/Mono_(software)" target="_blank">Mono</a>. A second reason is that I would like to keep the outside dependencies on OMeta# as small as possible.</p><p>OMeta is a beautiful in the same sense that mathematics can have a simple beauty. LISP has been referred to by some as "<a href="http://bc.tech.coop/blog/060224.html" target="_blank">The Most Important Idea in Computer Science</a>" largely because its core ideas could be expressed on a half page of the <a href="http://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf" target="_blank">LISP 1.5 manual</a> (page 13 to be exact). This elegance is similar to mathematics of <a href="http://en.wikipedia.org/wiki/Maxwell" target="_blank">Maxwell's Equations</a> describing electromagnetism. </p><p>It's my hope that I won't mess up the implementation to the point where this elegant beauty is lost. Currently it's way too ugly. I see some of the rough edges, but I'm sure you can help me discover others along with how to fix them. If this post sounds too complicated, it's not you, it's me. Let me know if something doesn't make sense and I'll try to provide clarification. </p><p>If you're interested in OMeta#, I highly encourage you to <a href="http://www.codeplex.com/ometasharp/SourceControl/ListDownloadableCommits.aspx" target="_blank">download the latest version of the source code</a> <a href="http://www.codeplex.com/ometasharp/" target="_blank">from CodePlex</a> and step through the <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=309791&changeSetId=15493" target="_blank">unit test runner</a> to see things get built up. </p><p>If you can, keep notes of all the places where you see me doing something and let me know about them either through comments or via email. In addition, I also highly recommend experimenting Alessandro Warth's great <a href="http://jarrett.cs.ucla.edu/ometa-js/" target="_blank">OMeta/JS</a> implementation via your web browser.</p><p>Happy OMeta-ing!</p><br /><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2008%2f07%2fbuilding-object-oriented-parasitic.html"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2008%2f07%2fbuilding-object-oriented-parasitic.html" border="0" alt="kick it on DotNetKicks.com" /></a>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.comtag:blogger.com,1999:blog-6800934446457898793.post-22911912401008727452008-06-24T00:36:00.003-04:002008-06-24T00:54:53.814-04:00OMeta#: Who? What? When? Where? Why?<p id="vyfd">What if programming language <i id="vyfd0">implementations</i> were <a id="vyfd1" href="http://en.wikipedia.org/wiki/Object_oriented">object-oriented</a>? What if you wanted to change one <i id="vyfd2"><a id="vyfd3" href="http://www.answers.com/itty-bitty&r=67">itty-bitty</a></i> part of your favorite language? Say you wanted to add an <a href="http://en.wikipedia.org/wiki/Exponentiation" target="_blank">exponentiation operator</a> (^^). How hard would it be? </p><p id="vyfd4">Wouldn't it be nice if you could "subclass" a language like C# and then add 5 lines of code to make it work and then use it? What if you could add Ruby-like <a id="vyfd5" href="http://www.thirdbit.net/articles/2007/08/01/10-things-you-should-know-about-method_missing/">method_missing</a> support in 20 lines?</p><p id="vyfd6">What if you could conceive of a new language and start experimenting with it in production code in an hour? What if it leveraged your knowledge of existing frameworks like .NET?</p><p>Let's imagine that it were possible. Let's say someone else created a basic calculator-like "language":</p><p id="vyfd8"><a id="vyfd9" href="http://bp2.blogger.com/_Zfbv3mHcYrc/SF6vVA8OTdI/AAAAAAAAAd8/01EO7B9Wwa4/s1600-h/OMetaBasicCalc.png"><img id="vyfd10" src="http://bp2.blogger.com/_Zfbv3mHcYrc/SF6vVA8OTdI/AAAAAAAAAd8/01EO7B9Wwa4/s400/OMetaBasicCalc.png" /></a> </p><p id="vyfd11">Even without knowing the syntax, you can probably figure out how it works since it's written very close to the <a id="vyfd12" href="http://en.wikipedia.org/wiki/Backus-Naur_form">standard way</a> of describing a language. If you give this language "3*4", it will respond with 12. If you give it "2^(3*4)", it'd respond with a nice syntax error message like "I don't know how to deal with the '^' symbol. Sorry!"</p><p id="vyfd13">But you could make it work by writing this object-oriented-like "subclass" of the language:</p><p id="vyfd14"><a id="vyfd15" href="http://bp1.blogger.com/_Zfbv3mHcYrc/SF6vy_-ii9I/AAAAAAAAAeE/FmgnCNZG-b8/s1600-h/OMetaExponentCalc.png"><img id="vyfd16" src="http://bp1.blogger.com/_Zfbv3mHcYrc/SF6vy_-ii9I/AAAAAAAAAeE/FmgnCNZG-b8/s400/OMetaExponentCalc.png" /></a> </p><p id="vyfd17">Now, giving this language "2^(3*4)" happily gives you 4096.</p><p id="vyfd18">This worked using simple inheritance. What if you wanted to compose your language from several other languages? That is, something like "<a id="vyfd19" href="http://en.wikipedia.org/wiki/Multiple_inheritance">multiple inheritance</a>" but without <a href="http://en.wikipedia.org/wiki/Multiple_inheritance#Criticisms" target="_blank">its problems</a>? What if we took a simpler approach and allowed a language to attempt to match elements of any other language?</p><p id="vyfd20">Let's say we want to build a scientific calculator that leverages some of the work we've already done. Instead of inheriting from it, we'll call out to it:</p><p id="vyfd21"><a id="vyfd22" href="http://bp1.blogger.com/_Zfbv3mHcYrc/SF6xI_7m1oI/AAAAAAAAAeM/IxwyBfXGdYU/s1600-h/OMetaScientificCalc.png"><img id="vyfd23" src="http://bp1.blogger.com/_Zfbv3mHcYrc/SF6xI_7m1oI/AAAAAAAAAeM/IxwyBfXGdYU/s400/OMetaScientificCalc.png" /></a> </p><p id="vyfd24">Now you can calculate expressions like "sqrt (1+2^3)!"</p><p id="vyfd25">What if such a <i id="vyfd26">meta</i> language (e.g. a language for describing other languages) existed? What would you do with it? How might it help you <a id="vyfd27" href="http://www.joelonsoftware.com/articles/GuerrillaInterviewing3.html">get things</a> <a id="vyfd28" href="http://steve-yegge.blogspot.com/2008/06/done-and-gets-things-smart.html">done</a> while producing extremely small, but very <i id="vyfd29">readable</i> code? What if creating a new language that <i id="vyfd30">perfectly fit</i> a problem your software was trying to solve was as easy as writing a simple <a id="vyfd31" href="http://en.wikipedia.org/wiki/Regular_expression">regular expression</a>? </p><p id="vyfd32">What if you could get all the whiz-bang, gotta-have tool support like <a id="vyfd33" href="http://en.wikipedia.org/wiki/Syntax_highlighting">syntax highlighting</a>, <a id="vyfd34" href="http://en.wikipedia.org/wiki/Debugging">interactive debugging</a>, and a <a id="vyfd35" href="http://en.wikipedia.org/wiki/Compiler">compiler</a> for it came at almost no extra cost? What if the barrier to entry for a new language was so low, that almost anyone could do it quickly?</p><p>This is what I've been thinking about for the past month or so. </p><p id="vyfd37"><b id="vyfd38">Who? & What?</b></p><p id="vyfd39">When I was doing some research for my "<a id="vyfd40" href="http://www.moserware.com/2008/04/towards-moores-law-software-part-3-of-3.html">Towards Moore's Law Software</a>" series, I came across a very interesting language called <a id="vyfd41" href="http://www.cs.ucla.edu/~awarth/ometa/">OMeta</a> which was created by <a id="vyfd42" href="http://www.cs.ucla.edu/~awarth/">Alessandro Warth</a> and <a id="vyfd43" href="http://piumarta.com/cv/bio.html">Ian Piumarta</a> with some inspiration from <a id="vyfd44" href="http://en.wikipedia.org/wiki/Alan_Kay">Alan Kay</a>. In their <a id="vyfd45" href="http://www.oopsla.org/oopsla2007/index.php?page=lds">2007 Dynamic Languages Symposium</a> <a id="vyfd46" href="http://www.cs.ucla.edu/~awarth/papers/dls07.pdf">paper</a>, the authors described OMeta as</p><blockquote id="vyfd47"><p id="vyfd48">".. a new object-oriented language for pattern matching. OMeta is based on a variant of <a id="vyfd49" href="http://en.wikipedia.org/wiki/Parsing_expression_grammar">Parsing Expression Grammars</a> (PEGs) —a recognition based foundation for describing syntax—which we have extended to handle arbitrary kinds of data. We show that OMeta’s general-purpose pattern matching provides a natural and convenient way for programmers to implement tokenizers, parsers, visitors, and tree transformers, all of which can be extended in interesting ways using familiar object-oriented mechanisms. This makes OMeta particularly well-suited as a medium for experimenting with new designs for programming languages and extensions to existing languages."</p></blockquote><p id="vyfd52">To be honest, I didn't really understand the paper when I first read it. It sounded cool, but it used a few new terms I hadn't heard of before. However, I couldn't help but be fascinated by OMeta's <em>readable</em> syntax. OMeta doesn't try to solve every problem involved with writing a complete program. It makes no claims about being a good general purpose programming language. But it <a id="vyfd53" href="http://en.wikipedia.org/wiki/Positioning_(marketing)">positions</a> itself by doing just one thing really well:</p><p id="vyfd54">Pattern matching. </p><p id="vyfd55">If you look at modern programming languages that are good for developing <em>other</em> languages, you'll notice that they usually have good pattern matching capabilities. For example, in <a id="vyfd56" href="http://en.wikipedia.org/wiki/ML_programming_language">ML</a> (which stands for meta-language), you can specify functions in terms of patterns. Here's how you can reverse a list:</p><p id="vyfd57"><a id="vyfd58" href="http://bp2.blogger.com/_Zfbv3mHcYrc/SF7a73YbceI/AAAAAAAAAeU/WHRZnc3Wwno/s1600-h/MLReverse.png"><img id="vyfd59" src="http://bp2.blogger.com/_Zfbv3mHcYrc/SF7a73YbceI/AAAAAAAAAeU/WHRZnc3Wwno/s400/MLReverse.png" /></a> </p><p id="vyfd60">This defines the <b id="vyfd61">fun</b>ction named "reverse." When it sees the "pattern" where the function is called with an empty list (nil), it just returns nil. However, when the function is passed in a list whose first element is "x" and the rest of the list is "xs", it will return the reverse of the rest of the list and then append the head of the list to the end. </p><p>If you think about it for a second, it's a really compact way of expressing how to reverse a list.</p><p id="vyfd62"><b id="vyfd63">Streams of <i id="vyfd64">Anything</i></b></p><p id="vyfd65">What I find interesting about OMeta is <i id="vyfd66">how</i> it matches patterns. OMeta can operate on a stream of <i id="vyfd67">anything</i>. This is useful because modern language implementations have several phases that work on different types of "things." Here's a simplified view of what a <a id="vyfd68" href="http://en.wikipedia.org/wiki/Compiler">compiler</a> does:</p><p id="vyfd69"><a id="vyfd70" href="http://bp2.blogger.com/_Zfbv3mHcYrc/SF7jgB5evZI/AAAAAAAAAec/wfMLpzDyejg/s1600-h/CompilerPhases.png"><img id="vyfd71" src="http://bp2.blogger.com/_Zfbv3mHcYrc/SF7jgB5evZI/AAAAAAAAAec/wfMLpzDyejg/s400/CompilerPhases.png" /></a> </p><p id="vyfd72">At the start of the process, you're working with individual characters from source code. The list of characters is converted to tokens by use of a scanner. This is how the characters 'i', 'n', and 't' become the "INT" token. The next phase combines tokens together to form a higher level view of the program, typically using a <a id="vyfd73" href="http://en.wikipedia.org/wiki/Tree_data_structure">tree data structure</a>. From that phase, several intermediate steps occur on the program (almost always in tree form), until it's finally pulled apart to make an executable program.</p><p id="vyfd74">Often, you have to use different tools at each phase. You might use <a id="vyfd75" href="http://en.wikipedia.org/wiki/Lex_programming_tool">lex</a> for the scanner (aka "<strong>lex</strong>er"), <a id="vyfd76" href="http://en.wikipedia.org/wiki/Yacc">Yacc</a> for the parser, and some sort of <a id="vyfd77" href="http://en.wikipedia.org/wiki/Visitor_pattern">visitor pattern</a> in your implementation language (e.g. C#) for many of the intermediate phases. With all of these different tools to learn, it's no wonder why most people don't even bother trying to create their own language. </p><p id="vyfd78">OMeta is different in that lets you use the same syntax for all phases. The only thing that is different is <i id="vyfd79">what</i> the input stream contains. At the start, the input stream is characters. In subsequent phases, it tokens, then trees, and then finally you produce your intended result. At each pass, your OMeta code has similar syntax.</p><p id="vyfd80"><b id="vyfd81">Passing the Match Around</b></p><p id="vyfd82">Another interesting bit about OMeta is how it goes about <em>finding </em>rules. Rules are defined in grammars which behave like classes in an object-oriented language. A grammar can "inherit" from another grammar. An added twist is that a grammar can call out to a "foreign" grammar. This makes it easier to build a language from many different reusable parts and allows for trivial "mashups" of several languages. </p><p>Additionally, if a rule has multiple "choices," then OMeta always tries to match the first choice, then the second, and so on until it achieves success. Although this seems obvious in hindsight, most parsers <a id="vyfd84" href="http://en.wikipedia.org/wiki/Context-free_grammar">don't have prioritized choices</a> and thus they make it easy to define ambiguous rules. For example, is "1-2-3" equal to "(1-2)-3" = -4 or "1-(2-3)" = 2? With prioritized choice, you make this explicit. If it successfully parses, then it has exactly one choice and therefore no ambiguities.</p><p id="vyfd85">The last really interesting aspect of OMeta's design is what it does when it matches a pattern. A pattern might consist of several sub-components. Each of these components (e.g. rules) can be captured into a variable. OMeta then feeds these variables into a "host" language. </p><p id="vyfd86"><a id="vyfd87" href="http://bp2.blogger.com/_Zfbv3mHcYrc/SF77O9LL3_I/AAAAAAAAAek/cs7N1F0qIlM/s1600-h/OMetaRuleDecomposition.png"><img id="vyfd88" src="http://bp2.blogger.com/_Zfbv3mHcYrc/SF77O9LL3_I/AAAAAAAAAek/cs7N1F0qIlM/s400/OMetaRuleDecomposition.png" /></a> </p><p id="vyfd89">OMeta <i id="vyfd90">doesn't care</i> what the host language is. It can be just about any language (e.g. JavaScript, LISP, C++, etc.). Typically, the host language is what the OMeta implementation itself was written in. The host language is free to do whatever it likes with the variables. OMeta is only responsible for getting them there. The <a id="vyfd91" href="http://www.cs.ucla.edu/~awarth/papers/dls07.pdf">OMeta paper</a> describes an implementation where the host language is <a id="vyfd92" href="http://piumarta.com/software/cola/">cola</a>. Other early versions were written in <a id="vyfd93" href="http://en.wikipedia.org/wiki/Squeak">Squeak</a> and use that as the host language. </p><p id="vyfd94">Alessandro has recently created a <a href="http://jarrett.cs.ucla.edu/ometa-js/#OMeta_Tutorial" target="_blank">JavaScript version</a> where you experiment with OMeta/JS (e.g. <b id="vyfd95">J</b>ava<b id="vyfd96">S</b>cript is the host language) in your browser. It's a very interesting playground. Some of the demonstrations range from the basic calculator language, to a type checker, to LISP, to even the OMeta compiler and code generator <i id="vyfd98">itself</i> and all of them are written in OMeta/JS. The playground website is neat to use because it shows the translated (generated) JavaScript code for the grammar (although the generated code needs to be put through a <a id="vyfd99" href="http://www.prettyprinter.de/">pretty printer</a> to make any sense of it).</p><p id="vyfd100"><b id="vyfd101">Why t</b><b id="vyfd102">he "#" in OMeta#?</b></p><p id="hdj2">After understanding the basics of OMeta/JS, I thought it would be interesting to have the host language be <i id="vyfd106">any</i> .NET language. I started to sketch out what this might look like by using my limited JavaScript ability and translating Alessandro's code to an equivalent functionality in C#. The result was the start of a project that needed a name. "OMeta#" seemed to fit the bill. </p><p id="hdj20">Besides, it just sounded better than other .NET-ism alternatives like "NOMeta", "OMeta.net", or "IronOMeta."</p><p id="z4y-">Some might ask, "Why .NET?" A subtle reason is that OMeta is useful for code generation. Code generation is a normal part of the .NET ecosystem even if people don't realize it. When people use the graphical designer in <a id="y4jg" title="Windows Forms" href="http://en.wikipedia.org/wiki/Windows_Forms">Windows Forms</a>, there is a code generator working behind the scenes writing code for their host language (typically C# or Visual Basic). When people write <a href="http://en.wikipedia.org/wiki/ASP.NET" target="_blank">ASP.NET</a> ".aspx" files, there is a hidden process that takes that HTML-like "language" and <a id="hdj21" href="http://msdn.microsoft.com/en-us/library/ms366723.aspx">compiles it</a> to a real DLL.</p><p id="l6wj">For example, ASP.NET transforms this:</p><p id="hdj22"><a id="hdj23" href="http://bp0.blogger.com/_Zfbv3mHcYrc/SGB9x23PQnI/AAAAAAAAAgM/c1Sb6qTEAoU/s1600-h/AspNetHelloWorldAspx.png"><img id="hdj24" style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" alt="AspNetHelloWorldAspx" src="http://bp0.blogger.com/_Zfbv3mHcYrc/SGB9x23PQnI/AAAAAAAAAgM/c1Sb6qTEAoU/s400/AspNetHelloWorldAspx.png" /></a> </p><p id="hdj25">Into this generated code:</p><p id="hdj26"><a id="hdj27" href="http://bp2.blogger.com/_Zfbv3mHcYrc/SF-nnXKgxQI/AAAAAAAAAfE/E2sbgLZYr6M/s1600-h/AspNetHelloWorldGenerated.png"><img id="hdj28" src="http://bp2.blogger.com/_Zfbv3mHcYrc/SF-nnXKgxQI/AAAAAAAAAfE/E2sbgLZYr6M/s400/AspNetHelloWorldGenerated.png" /></a> </p><p id="hdj29">I wanted to bring a similar "it just works" illusion to the .NET world with OMeta#.<a id="vyfd104" title="'Footsteps @ Porthleven' by Darren Copley" href="http://www.flickr.com/photos/97607362@N00/1102203511/" target="_blank"><img id="vyfd105" style="MARGIN: 5px 0px 5px 10px" src="http://bp2.blogger.com/_Zfbv3mHcYrc/SF8On2eKQpI/AAAAAAAAAes/bndJjsBOEhg/s400/Footsteps.jpg" align="right" /></a></p><p id="vyfd107">With the encouragement of <a id="hdj210" href="http://www.cs.ucla.edu/~awarth/">Alessandro</a>, I started working on some of the supporting "goo" that would be required to get OMeta working on the .NET's <a href="http://en.wikipedia.org/wiki/Common_Language_Runtime" target="_blank">Common Language Runtime</a> (CLR). This isn't trivial because the CLR has stricter type system than languages like JavaScript. Also, since I chose C# as the implementation language, I had to make sure that the code passed all of the static type checking it performs at compile time. It's been a slow start, but I have been able to make a few steps towards making it work.</p><p id="vyfd111">One pragmatic question is why even bother adding another language, or rather, meta-language to the .NET world? Why not just get proficient at another toolset that is decent at creating language like <a id="vyfd112" href="http://www.antlr.org/" target="_blank">ANTLR</a>, <a id="vyfd113" href="http://www.codeplex.com/irony" target="_blank">Irony</a>, <a id="vyfd114" href="http://jparsec.codehaus.org/NParsec+Tutorial" target="_blank">NParsec</a>, or <a id="vyfd115" href="http://en.wikipedia.org/wiki/IronRuby" target="_blank">IronRuby</a>? What about using <a id="vyfd116" href="http://langnetsymposium.com/talks/3-03%20-%20Parsing%20Expression%20Grammars%20in%20FSharp%20-%20Harry%20Pierson.html" target="_blank">Parsing Expression Grammars in F#</a> or <a id="vyfd117" href="http://www.manning.com/rahien/" target="_blank">writing Domain Specific Languages in Boo</a> with its extensible compiler pipeline?</p><p>Ultimately, all of those tools are pretty good, but none of them did exactly what I was looking for. Some came close, but none of them seem capable of matching OMeta's power and simplicity.</p><p>Another reason was that I knew that writing an implementation of OMeta from the ground up would really help me "<a id="vyfd120" href="http://compsci.ca/blog/you-dont-know-that-programming-language/">know</a>" how it works. </p><p>More importantly, I thought it would be <em>fun</em> to work on. I'm not a language expert. I'll never reach the level of someone like <a href="http://en.wikipedia.org/wiki/Anders_Hejlsberg" target="_blank">Anders</a>, but I was one of those odd kids that actually liked my compilers and programming languages classes. I also enjoyed <a id="vyfd121" href="http://www.langnetsymposium.com/talks.asp" target="_blank">the talks</a> from this year's <a id="vyfd122" href="http://www.langnetsymposium.com/" target="_blank">Lang.NET symposium</a> (even if I didn't understand a lot of things).</p><p id="vyfd126"><b id="vyfd127">The Grand OMeta# Vision</b></p><p id="vyfd128">The grand vision for OMeta# is to make it <i id="hdj211"><b id="hdj212">really simple</b></i> to create languages that "just work." It probably won't have the world's best performance, but it should be decent enough for almost all practical applications. It would be neat to have OMeta# (or something like it) be used to do the following:</p><ol id="vyfd130"><li id="vyfd132"><strong>Serve as a common, unified way for developing languages on the .NET platform</strong> — There are many helpful, yet often different "tools" out there for various stages of language design. I mentioned a few earlier, but some of the more advanced ones include the new <a href="http://en.wikipedia.org/wiki/Dynamic_Language_Runtime" target="_blank">Dynamic Language Runtime</a> (DLR) and <a href="http://en.wikipedia.org/wiki/Phoenix_(compiler_framework)" target="_blank">Phoenix compiler framework</a>. It would be neat to have a language that abstracted away some of these tools into a clean syntax like OMeta. That way, you'd get the benefit of these tools without having to constantly learn different ways of manipulating the concepts that can be expressed simply. </li><br /><li><strong>Factor out the "goo" of language development</strong> — For a language to be taken seriously, it has to have things like syntax highlighting, interactive debugging, and a decent compiler. Each of these takes time to implement and often involves a high learning curve. It would be great if you could just make some minor annotations to your OMeta grammar and then these features would "just work." </li><br /><li id="vyfd134"><strong>Useful for teaching</strong> — One of my favorite textbooks in college was "Programming Languages: An Interpreter-Based Approach" by <a href="http://www.eecs.harvard.edu/~nr/" target="_blank">Ramsey</a> (et. al.). Our class used a "draft" version of it (and it still hasn't been published yet). It took a very interesting approach towards teaching programming languages. In order to understand a language like <a href="http://en.wikipedia.org/wiki/Scheme_(programming_language)" target="_blank">Scheme</a>, you had to implement an interpreter for it in C or ML. I really liked this approach because getting your hands dirty with implementing the language typically leads to a better understanding of it. I would love to have the ability to implement this type of approach in something like OMeta. You could understand the essence of a language by only having to understand a page or two of code. It would also let you learn by experimenting with adding small features to existing languages. </li><br /><li id="vyfd135"><strong>Practical for production use</strong> — For anything to really succeed at moving <a href="http://www.moserware.com/2008/04/towards-moores-law-software-part-1-of-3.html" target="_blank">towards a Moore's Law increase in expressiveness</a>, it has to have reasonable quality. I can imagine OMeta# being introduced into real production projects by first integrating a small amount of OMeta's "generated" a project and then over time implementing more and more parts of the application in this highly specific language. For this to occur, it has to be reliable and simple to use. </li><br /></ol><p id="vyfd136"><b id="vyfd137">When? Where? </b></p><p id="vyfd138">All of the parts of the vision are still in the future. To make them a reality will require more than just a single person or even a couple of people. I'm <strike>naïve</strike> crazy enough to think that it's actually possible. In an effort not to "<a id="vyfd140" href="http://www.codinghorror.com/blog/archives/001134.html" target="_blank">go dark</a>," I've decided to be fairly open about the design and implementation of OMeta#. The current state of the code isn't even alpha quality yet. Despite all of these shortcomings, I've <a href="http://www.codeplex.com/ometasharp">posted what I have so far on CodePlex</a> and will continue to make updates to it. </p><p>Keeping in the tradition of other OMeta implementations, I've licensed it under the <a href="http://en.wikipedia.org/wiki/MIT_License" target="_blank">MIT License</a> so that you can use, experiment, play, and modify it without any licensing concerns.</p><p id="vyfd141">The first interesting result is that I've been able to get a complete end to end demo working for an extremely simple grammar that matches numbers. I fed this input grammar written in OMeta/C#:</p><p><a href="http://bp2.blogger.com/_Zfbv3mHcYrc/SGBI_NbgBMI/AAAAAAAAAf8/v1D6MAm1G_8/s1600-h/OMetaCSBootstrappedNumberParser.png" target="_blank"><img src="http://bp2.blogger.com/_Zfbv3mHcYrc/SGBI_NbgBMI/AAAAAAAAAf8/v1D6MAm1G_8/s400/OMetaCSBootstrappedNumberParser.png" /></a> </p><p>into my OMeta compiler/translator and successfully had it generate <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264623&changeSetId=12094" target="_blank">this output C# file</a>.</p><p id="vyfd143">There is still a ton of work left. It's quite possible that some of the design decisions I've made so far need to be challenged and redesigned. I'd love to get feedback from anyone that's interested.</p><p>What do you think? Do you think OMeta fills a unique niche? Do you think it would be useful to have as a tool in .NET? Would you want to help out making "The Grand OMeta# Vision" happen? If so, what parts can you help out with?</p><p id="vyfd144">I'm curious to hear your thoughts. In my next post, I hope to cover some of the technical details for how my current implementation works "under the covers."</p><p>P.S. Many thanks to Alessandro Warth for creating this beautiful language and helping me get started!</p><br /><br /><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2008%2f06%2fometa-who-what-when-where-why.html"><img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2008%2f06%2fometa-who-what-when-where-why.html" border="0" /></a>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.comtag:blogger.com,1999:blog-6800934446457898793.post-2517160165828837802008-05-21T22:00:00.001-04:002008-05-21T22:00:24.684-04:00Who Is This "Licklider" Guy?<center id="gw771"><a id="gw772" href="http://en.wikipedia.org/wiki/J._C._R._Licklider"><img id="gw773" style="MARGIN: 0px 10px 10px 0px" src="http://bp2.blogger.com/_Zfbv3mHcYrc/SC7TdNj-vLI/AAAAAAAAAcM/bG1E5KuW-9k/s400/J__C__R__Licklider.jpg" /></a></center><p id="gw775"><i id="pn7n0">Who are they talking about? </i><i id="pn7n1">Why haven't I ever heard of him?</i></p><p id="gw777">I was at <a id="gw778" href="http://www.sri.com/">SRI</a>, a research institute by the <a id="gw779" href="http://www.stanford.edu/">Stanford</a> campus. Around me was a lively group of some of the best minds in Computer Science, some of them has had their PhDs in the field for 40 <i>years</i>. I had the honor of being the <i id="pn7n2">least</i> credentialed person in the room. As I listened to some of the discussions, I noticed that they seemed to keep bringing up the name "<a id="gw7712" href="http://en.wikipedia.org/wiki/J._C._R._Licklider">Licklider</a>." Sometimes they'd just call him "Lick." Other times they'd mention projects along with his name that I hadn't heard about before like "<a id="gw7713" href="http://en.wikipedia.org/wiki/Project_MAC">Project MAC</a>." Since the guys talked so much about him, I knew I had to find out more about who this "Lick" guy was. One of them suggested that I read the book <a id="gw7714" href="http://www.amazon.com/Dream-Machine-Licklider-Revolution-Computing/dp/0670899763/ref=ed_oe_h">"The Dream Machine: J.C.R. Licklider and the Revolution That Made Computing Personal</a>" by <a id="gw7715" href="http://mmwaldrop.com/">M. Mitchell Waldrop</a>. <a id="gw7716" href="http://bp2.blogger.com/_Zfbv3mHcYrc/SC8yu9j-vMI/AAAAAAAAAcU/kCOiBRWJ_lw/s1600-h/EyesOverTheDreamMachine.JPG"><img id="gw7717" style="MARGIN: 5px 0px 10px 5px" src="http://bp2.blogger.com/_Zfbv3mHcYrc/SC8yu9j-vMI/AAAAAAAAAcU/kCOiBRWJ_lw/s320/EyesOverTheDreamMachine.JPG" align="right" /></a></p><p id="gw7718">My local library had the book. I was a bit worried when I saw that it hadn't been checked out for three years. "Hmm... maybe it's not that good?" I thought. </p><p id="gw7719">I was pleasantly surprised.</p><p id="gw7720">At about 500 pages, it's not a small book. Fortunately, I was able to finish it just before the library forced me to return it since I hit the maximum amount of renewals on it. </p><p id="gw7721">The book put me on a journey that filled in a lot of details about computing history that I didn't even know I was clueless about while weaving a story about a man from Missouri. Although his full name was Joseph Carl Robnett Licklider, just about everyone called him "Lick," a name he acquired in his fraternity days. </p><p id="gw7723">Lick's story is bigger than just one guy. It's a story that goes back to the dawn of computing right up to the personal computer. While reading the book, I had a lot of "Aha!" moments that helped fill me into the colorful history of computing. For example, I had heard a lot about <a id="gw7724" href="http://en.wikipedia.org/wiki/Digital_Equipment_Corporation">DEC</a>'s <a id="gw7725" href="http://en.wikipedia.org/wiki/Programmed_Data_Processor">PDP</a> system, but it was interesting to know that they were specifically called "Programmed Data Processors" instead of "computers" because congress was pressured not to spend any more money on computers at the time. By itself, facts like these seem to be obscure trivia, but when you read about the politics of funding at the time, you can really understand that DEC had few alternatives.</p><p id="gw7726">I can't recall ever hearing Licklider's name before that meeting at SRI, but that's probably because I didn't try too hard. As a kid interested in computers growing up in the 1990's, I really focused my attention on learning about one person - <a id="gw7727" href="http://en.wikipedia.org/wiki/Bill_Gates">Bill Gates</a>. I read <a id="gw7728" href="http://www.amazon.com/Hard-Drive-Making-Microsoft-Empire/dp/0887306292">several</a> <a id="gw7729" href="http://www.amazon.com/Road-Ahead-Bill-Gates/dp/0140257276">books</a> about him and had a reasonably good idea of his background and the history of <a id="gw7730" href="http://en.wikipedia.org/wiki/Traf-O-Data">Traf-O-Data</a>, <a id="gw7731" href="http://en.wikipedia.org/wiki/Microsoft">Microsoft</a> and some of its products like <a id="gw7732" href="http://en.wikipedia.org/wiki/Microsoft_BASIC">BASIC</a>, <a id="gw7733" href="http://en.wikipedia.org/wiki/MS-DOS">DOS</a>, <a id="gw7734" href="http://en.wikipedia.org/wiki/OS/2">OS/2</a>, <a id="gw7735" href="http://en.wikipedia.org/wiki/Microsoft_Windows">Windows</a>, and <a id="gw7736" href="http://en.wikipedia.org/wiki/Windows_nt">NT</a>. Perhaps in the back of my mind I thought that learning about him would me emulate his success and make me <strike id="pn7n3">millions</strike>billions. Too bad that didn't work out.</p><p id="gw7737">In addition to the books, my other major source of information was when I watched <a id="gw7738" href="http://en.wikipedia.org/wiki/Robert_X._Cringely">Bob Cringely</a>'s <a id="gw7739" href="http://www.pbs.org/nerds/">Triumph of the Nerds</a> on PBS in the summer before I started high school. In hindsight, after reading this book I really wish I would have watched the 1998 follow-on to the series called "<a id="gw7740" href="http://www.pbs.org/opb/nerds2.0.1/">Nerds 2.01: A Brief History of the Internet</a>." I would have at least heard about Licklider and the computing days before Microsoft and Apple and not been so clueless back at that room in SRI.</p><p id="gw7741">What a story it is! It's not really just about Lick; it's about how he helped build a community that fostered the explosive computing growth in the 1960's right through the 70's and 80's.</p><p id="gw7742">Since I <a id="gw7743" href="http://www.moserware.com/2008/03/what-does-it-take-to-become-grandmaster.html">like to ask others</a> what stuck out in books that they've read, I thought I'd share some things I found interesting:</p><p><b id="gw7745">22 Days of Beeps Can Change a Nation</b><img id="gw7747" style="MARGIN: 0px 5px 5px 0px" src="http://bp0.blogger.com/_Zfbv3mHcYrc/SC9dYdj-vNI/AAAAAAAAAcc/6rN5vGcd-RQ/s200/Sputnik_asm.jpg" align="left" /></p><p>Chapter 6 opens on a rocket launch pad in the early morning of October 1957 at a top secret Soviet Union location. When the rocket took off and deployed its payload, the world came to know <a id="gw7749" href="http://en.wikipedia.org/wiki/Sputnik_1">Sputnik</a> by its incessant <i id="gw7750">beep beep beep</i> transmissions.</p><p id="gw7751">Waldrop quotes this account:</p><blockquote id="pn7n4"><p id="pn7n5">"[<i id="gw7752">Sputnik</i>'s] two transmitters would fail twenty-three days after launch - but their arrogant beeping would continue to sound in the American memory for years to come... Gone forever in this country was the myth of American superiority in all things technical and scientific." (p. 197)</p></blockquote><p id="gw7753">Although the U.S. had rockets under development that were more sophisticated than the Soviet ones, <a id="gw7754" href="http://www.pbs.org/wgbh/nova/sputnik/program.html">it was a huge blow to American pride</a> and there was a large public outcry. Everyone made the connection: if the Soviets could launch a satellite into space, they could probably launch a missile into any major U.S. city. </p><p id="pn7n6">One famous result of this perceived threat was <a id="gw7755" href="http://en.wikipedia.org/wiki/Dwight_D._Eisenhower">President Eisenhower</a>'s endorsement of "a plan to consolidate all the Pentagon's space research under a new civilian agency reporting directly to the secretary of defense. It would be called the <a id="gw7756" href="http://en.wikipedia.org/wiki/Defense_Advanced_Research_Projects_Agency#History">Advanced Research Projects Agency</a>, or ARPA." </p><p>Well it didn't <i id="gw7757">quite</i> work out exactly as planned. </p><p>Before ARPA opened for business, it had already been split up. The <a id="gw7758" href="http://en.wikipedia.org/wiki/NASA">National Aeronautics and Space Administration</a> (<a id="gw7759" href="http://www.nasa.gov/">NASA</a>) would handle all the non-military space projects and the services would get a large amount their funding back to handle most of their development projects. This left ARPA with "the kind of beyond-the-cutting-edge stuff that the services were willing to do without." (p. 198)</p><p id="gw7760">ARPA wasn't initially interested in computers. To them, they were really only helpful for things like accounting and payroll. This changed when ARPA was tasked to research new command and control ideas that would require a lot of data processing. This seemed like an ideal fit for computers. Licklider was asked to come over to ARPA and lead the new project.</p><p id="gw7761">He didn't want to take the job at first. He was already doing interesting things with computers and was so busy working on fleshing out his ideas of computer assisted "libraries of the future" to even think about burying himself in "the bureaucratic limbo of Washington." (p. 201)</p><p id="gw7762">Once he warmed up to the idea of going to ARPA, he began thinking that the command and control concept was ultimately a man-machine symbiosis, something he had been thinking about for years.</p><p id="gw7763"><a id="gw7764" href="http://en.wikipedia.org/wiki/Fig_wasp"><img id="gw7765" style="MARGIN: 5px 5px 5px 0px" src="http://bp2.blogger.com/_Zfbv3mHcYrc/SC-ON9j-vRI/AAAAAAAAAc8/XjwAVNDbW-E/s200/Blastophaga_psenes.jpg" align="left" /></a>In March of 1960, he published his famous "<a id="gw7766" href="http://www.columbia.edu/~jrh29/licklider/man-computer_symbiosis.html">Man-Computer Symbiosis</a>" which began: </p><blockquote id="gw7767"><p id="gw7768">"The fig tree is pollinated only by the insect Blastophaga grossorun. The larva of the insect lives in the ovary of the fig tree, and there it gets its food. The tree and the insect are thus heavily interdependent: the tree cannot reproduce without the insect; the insect cannot eat without the tree; together, they constitute not only a viable but a productive and thriving partnership. This cooperative 'living together in intimate association, or even close union, of two dissimilar organisms' is called symbiosis.</p><p id="gw7769">'Man-computer symbiosis' is a subclass of man-machine systems. There are many man-machine systems. At present, however, there are no man-computer symbioses. The purposes of this paper are to present the concept and, hopefully, to foster the development of man-computer symbiosis by analyzing some problems of interaction between men and computing machines, calling attention to applicable principles of man-machine engineering, and pointing out a few questions to which research answers are needed. The hope is that, in not too many years, human brains and computing machines will be coupled together very tightly, and that the resulting partnership will think as no human brain has ever thought and process data in a way not approached by the information-handling machines we know today."</p></blockquote><p id="gw7770">This might not seem radical in 2008, but it was revolutionary back in the 1960's when most people could only think of computers as batch processing machines. Lick saw computers in a symbiosis where humans could do the thinking and the machines would do the "algorithmic chores they were so good at" (p.148). In order to find out how much of a benefit they'd be, he did an experiment on himself and found to his horror that he spent 85% of his time just "getting into a position to think, to make a decision, to learn something I needed to know." The rest of the time was just clerical or mechanical. Computers would be a perfect fit to handle all the dreary stuff that got in the way of <i id="pn7n7">real</i> thinking.</p><p id="gw7771">Lick knew that he could start making the man-computer symbiosis concept real and get the government to pay for it through his association with ARPA. Lick's view was "that the problems of command and control were essentially problems of man-computer interaction. I thought it was just ridiculous having command-and-control systems based on batch processing. Who can direct a battle when he's got to write a program in the middle of a battle?" (p. 202)</p><p id="gw7772">On the next page we see:</p><blockquote id="gw7773"><p id="gw7774">"Improbably, miraculously, through some once-in-a-lifetime alignment of all the right planets, ARPA was offering him a chance to turn his vision into a reality. He could reinvent the whole field of computing. He could transform those giant calculating machines into full-fledged partners in a human creativity. He could create 'information utilities' that spanned the continent. He could democratize information by opening up vast libraries of material to instant access by anyone. And he could do it all with the Pentagon's money." (p. 203)</p></blockquote><p id="gw7775">And boy did he ever: </p><blockquote id="gw7776"><p id="gw7777">"[The professional bureaucrats] had a history of giving grants to individual people in twenty-thousand-dollar chunks. But Lick was talking about millions of dollars and whole teams of people. It was as though these folks had encountered this alien creature: friendly, but strange." (p. 206)</p></blockquote><p id="gw7778">In addition to funding research organizations like <a id="gw7779" href="http://en.wikipedia.org/wiki/System_Development_Corporation">SDC</a>, <a id="gw7780" href="http://en.wikipedia.org/wiki/RAND">RAND</a>, and <a id="gw7781" href="http://en.wikipedia.org/wiki/SRI_International">SRI</a>, Lick is remembered for helping fund the new computer science departments at <a id="gw7782" href="http://www.cs.berkeley.edu/">Berkeley</a>, <a id="gw7783" href="http://www-cs.stanford.edu/">Stanford</a>, <a id="gw7784" href="http://www.cs.cmu.edu/">Carnegie Mellon</a>, and perhaps most famously, <a id="gw7785" href="http://www.eecs.mit.edu/">MIT</a>. Lick's funding at MIT went towards a system that would put together several foundational ideas needed for his man-computer symbiosis. The goal was "Machine-Aided-Cognition," but since computer time was hard to come by and they had to invent a lot of the concepts for <a id="gw7786" href="http://en.wikipedia.org/wiki/Time-sharing">time-sharing</a> to allow multiple people to access a computer at once, the project also went by the name "Multiple Access Computer." Regardless of which one you chose, the acronym was the same. </p><p id="gw7787">"<i id="gw7788">So that's the Project MAC </i><i id="gw7789">the folks in the room were talking about,</i>" I thought as I read about it.</p><p id="gw7790">Project MAC would lay a lot of the foundations for modern operating systems. Examples include technologies like <a id="pn7n8" href="http://en.wikipedia.org/wiki/Computer_multitasking">multitasking</a> and <a id="pn7n9" href="http://en.wikipedia.org/wiki/File_system">file systems</a> to policies such as regular backups to protect themselves from their mistakes. They had to introduce passwords to stop some people from stealing computer time as well as ideas from unpublished academic papers. Unix and the C language it was written in was an offshoot of this project as an attempt to write a <i id="pn7n10">simpler</i> version than what the Project MAC team was trying to accomplish. </p><p id="pn7n11">And yet, Project MAC was just <i id="pn7n12">one</i> of the many projects that Lick was funding and tracking. To the outside observer, all of the projects seemed like an ad hoc mess rather than a carefully crafted plan. Lick knew that his man-computer symbiosis dream would need to be maintained by more than just him. Waldrop writes:</p><p id="gw7793">"Lick realized, if this vision was ever going to outlast his tenure at ARPA, he would somehow have to forge all these groups into a self-reinforcing, self-sustaining community." (p. 225)</p><p id="pn7n13">One such example of how he did this was his famous 1963 <a id="gw7795" href="http://www.kurzweilai.net/articles/art0366.html?printable=1">memo</a> which began: "[to the] Members and Affiliates of the Intergalactic Computer Network." In his mind, Lick was referring to a <i id="pn7n15">human</i> network. He continued: "It is evident that we have among us a collection of individual (personal and/or organizational) aspirations, efforts, activities, and projects." The challenge now was to exploit "the possibilities for mutual advantage". He went on to describe a connected system that would keep all the research projects together, a network focused on human thoughts but connected by wires. In essence, the early signs of the Internet.</p><p id="gw7796">But it took some time to materialize and didn't happen during Lick's ARPA tenure.</p><p id="gw7797">He did make progress. Due to the computing focus that Lick had caused, his ARPA division was given the title "Information Processing Techniques Office" (IPTO). After his two year tenure at ARPA, Lick handed the reins over to a young <a id="gw7798" href="http://en.wikipedia.org/wiki/Ivan_Sutherland">Ivan Sutherland</a> (creator of <a id="gw7799" href="http://en.wikipedia.org/wiki/Sketchpad">Sketchpad</a>, which launched the field computer graphics and computer aided design). When Sutherland finished his tenure, <a id="gw77100" href="http://en.wikipedia.org/wiki/Robert_Taylor_(computer_scientist)">Bob Taylor</a> would take over and proceed to actually make Lick's "Intergalactic Network" of people a real physical thing by linking ARPA people together into <a id="gw77101" href="http://en.wikipedia.org/wiki/ARPANET">ARPANET</a>, <i id="gw77102">the</i> direct predecessor of the Internet. </p><p id="gw77103">The <a id="gw77104" href="http://en.wikipedia.org/wiki/ARPANET#Initial_ARPA_deployment">first message went across it</a> at 10:30 PM on October 29, 1969. </p><p id="gw77105">Two interesting things from the book stand out right around this period of time. The first was that the height of the <a id="gw77106" href="http://en.wikipedia.org/wiki/Vietnam_War">Vietnam War</a> was taking a huge toll on the nation, both in terms of people and dollars. In a reported attempt to limit spending on the war, Montana senator <a id="pn7n16" href="http://en.wikipedia.org/wiki/Mansfield_Amendment">Mike Mansfield</a> proposed an amendment that would prevent the Defense Department from "[carrying] out any research project or study unless such project or study has a direct and apparent relationship to a specific military function." </p><p id="pn7n17">The practical effect of the "<a id="ceea" title="Mansfield Amendmant" href="http://nsf.gov/nsb/documents/2000/nsb00215/nsb50/1970/mansfield.html">Mansfield Amendment</a>" was that it diverted a large percentage of people's time into writing how their project had a "direct and apparent" relevancy. It's also one of the largest reasons why ARPA is now known as <a id="pn7n18" href="http://en.wikipedia.org/wiki/DARPA">DARPA</a>:</p><blockquote id="pn7n19"><p id="pn7n20">"In retrospect, moreover, [the Mansfield Amendment] came to be seen as the symbolic watershed for ARPA, the point at which it started its downhill slide from being a cutting-edge agency that was blessedly free to take risks to being an ordinary agency that was cautious and risk-averse." (p. 395)</p></blockquote><p id="gw77108">The second big thing was that in May of 1969, Xerox was making a <i id="gw77109">lot</i> of money selling copiers. But their management knew they had to be more than a one product company. In an attempt to branch out and "go digital," they purchased <a id="gw77110" href="http://en.wikipedia.org/wiki/Scientific_Data_Systems">Scientific Data Systems</a> (SDS). However, they had a problem: the company was largely computer illiterate. They needed to go out and recruit the best computer people the world had. One of their first hires was none other than former ARPA IPTO director Bob Taylor. Taylor would go on to attract many from Lick's "Intergalactic Network" ARPA community who had been distressed by the Mansfield Amendment and its research cutting implications.</p><p id="gw77111">The resulting <a id="pn7n21" href="http://en.wikipedia.org/wiki/Xerox_Parc">Xerox Palo Alto Research Center</a> (PARC) was <i id="gw77112">the</i> place to be in the 1970's. It fostered freedom to explore ideas just like the early ARPA days since its backers were willing to invest in long-term innovation. Its <a id="pn7n22" href="http://www.wheels.org/spacewar/stone/rolling_stone.html">anti-corporate culture</a> included meetings filled with beanbag chairs which prevented people from leaping out of their chair to argue with someone. This 'helped' you hear them out. PARC would go on to create the foundations of personal computing as we know it with their <a id="gw77113" href="http://en.wikipedia.org/wiki/Xerox_Alto">Alto</a> personal computer which was named after the city they were in. The Alto had new ideas like bitmapped displays, windows, an Ethernet network, WYSIWYG word processing, laser printing, and roots of modern object oriented programming. Unfortunately, Xerox's management didn't quite understand the business value of what their PARC guys were creating. Additionally, the guys inside PARC had a hard time creating a clear path and business model for getting their ideas to market. There was one notable exception. Waldrop writes:</p><blockquote id="gw77114">"If [<a id="gw77116" href="http://en.wikipedia.org/wiki/Jack_Goldman">Jack Goldman</a>] hadn't thrown a tantrum [in order to get the business guys to listen], they might just have rejected the laser printer itself - the <i id="pn7n23">one</i> PARC-bred product that would eventually earn billions for Xerox and repay its investment in PARC many times over." (p. 392)</blockquote><p id="gw77117"><a id="pn7n24" href="http://en.wikipedia.org/wiki/Steve_jobs">Steve Jobs</a>, along with some other engineers, would visit PARC in December of 1979 for a demonstration of the Alto system. Jobs was so enamored by the graphical interface that he saw that he didn't even explore the object oriented programming and networking ideas. During the visit, Jobs reportedly exclaimed "Why hasn't this company brought this to market?" (p. 443) He didn't wait around for Xerox. Apple's first graphical computer, "<a id="pn7n25" href="http://en.wikipedia.org/wiki/Apple_Lisa">Lisa</a>," 'borrowed' several ideas from the Alto. When the Lisa and <a id="pn7n26" href="http://en.wikipedia.org/wiki/IBM_PC">IBM PC</a> hit the market in the early 80's, the guys inside PARC realized that <a id="pn7n27" href="http://www.amazon.com/Fumbling-Future-Invented-Personal-Computer/dp/1583482660">Xerox had blown a huge opportunity</a>. Many jumped ship. One example was <a id="pn7n28" href="http://en.wikipedia.org/wiki/Charles_Simonyi">Charles Simonyi</a>, who took his ideas <a id="pn7n29" href="http://en.wikipedia.org/wiki/Bravo_%28software%29">Bravo</a> word processing ideas north to a relatively new company in Washington named Microsoft. It was a huge difference in culture. Simonyi's commented on the contrast:</p><blockquote id="pn7n30">"It was like going into the graveyard or retirement home before going into the maternity ward. You could see that Microsoft could do things one hundred times faster, literally, I'm not kidding. Six years from that point, we overtook Xerox in market valuation." (p. 449)</blockquote><p id="gw77118">And that brought me full circle back to the pop culture history I was more familiar with. Throughout the years Lick would stay involved in some part with the research community, sometimes getting bogged down with management tasks which he despised. He would teach at MIT through the 80s with students that would only later realize all that he had done. Failing health caused him to pass away at the age of 75 on June 26, 1990: just before the world at large would come to use the "Intergalactic Network." </p><p id="gw77119">Lick was known for being quite modest about his contributions, often minimizing his role. When asked about what he did, he said:</p><blockquote id="pn7n32">"I think that I found a lot of bright people and got them working in this area. I got it moving. [And it was] a fantastic community. I guess that's the word. It was more than just a collection of bright people. It was a thing that organized itself into a community, so that there was some competition and some cooperation, and it resulted in the emergence of a field." (p. 258)</blockquote><p id="pn7n34">So <i id="gw77123">that's</i> why they kept talking about him. Now I get it. </p><p id="pn7n35">Lick organized a community that would change the computing world. He realized that it's ultimately the people that matter. I think that our industry puts too much emphasis on technology and tends to marginalize people. I think that one of the first steps to reverse this trend is to understand the contributions of its founders like Lick. </p><p id="pn7n36">"The Dream Machine" was a good book. I recommend it to anyone who might be curious about what happened in computing before the Microsoft, Apple, and especially Google days. From the early days of <a id="pn7n37" href="http://en.wikipedia.org/wiki/Von_Neumann">Von Neumann</a> and <a id="pn7n38" href="http://en.wikipedia.org/wiki/Alan_Turing">Turing</a>, right up to the 90's, Waldrop's detailed research helped <a id="pn7n39" href="http://www.technologyreview.com/Infotech/12040/page1/">the story</a> come alive. The book appears to be out of print, but it is well worth a visit to your library or getting a <a id="pn7n40" href="http://product.half.ebay.com/The-Dream-Machine_W0QQprZ1845304QQtgZinfo">used</a> copy. </p><p id="gw77127">If you made it this far, I'd really love to hear your comments on a few related questions:</p><ul id="pn7n41"><li id="pn7n42">Had you heard of Licklider before? If so, where? What sticks out in your mind about Lick? </li><li id="pn7n43">What do you think about Lick's funding and management strategy in the early days of ARPA's IPTO? </li><li>What do you think of Lick's comparison of the Fig Wasp and Fig Tree to a man-computer relationship? Do you think we've obtained the man-computer symbiosis he was referring to? </li><li id="pn7n44">What about PARC? It could still be considered success since the laser printer paid for Xerox's investment in it. However, as Steve Jobs points out, they could have been the IBM of the 90's but blew their chance. What do you think? </li><li id="pn7n45">What do you think about the Mansfield Amendment of the 1970 fiscal year? It's easy to criticize things in hindsight. If it was 1969 and you didn't know the future, which side would you have honestly taken? How would you have defended your position? </li><li>If you read this book or similar books, what is most memorable to you about the period from the 1930's through the late 80's that you think most people don't know about? </li></ul>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.comtag:blogger.com,1999:blog-6800934446457898793.post-59503513089857421302008-04-26T21:09:00.009-04:002008-04-26T22:45:44.276-04:00My "Better Know a Framework" Talk at IndyCodeCamp<p>The podcast "<a href="http://www.dotnetrocks.com/">.NET Rocks</a>!" has a segment called "Better Know A Framework" at the start of every show. The point of the short segment is to simply raise awareness of perhaps lesser known areas of the .net framework. I've found that it's a great way to learn about some things that I simply haven't looked at before.</p><p>When <a href="http://www.aaronlerch.com/blog/">Aaron Lerch</a> asked for session proposals for the <a href="http://www.indycodecamp.com/">IndyCodeCamp</a> that he and some others were organizing, I thought it'd be fun to have a "Better Know a Framework" session that had much of the same feel as the segment on the show.</p><p>In order to prepare for <a href="http://www.indycodecamp.com/Sessions/tabid/438/Default.aspx#framework">the talk</a>, I went back through every segment and made a few notes on what parts of the framework was covered as well as documentation links for more information. In case that work might helpful to anyone else, I'm including it as an "appendix" to this post.</p><br /><a href="http://bp2.blogger.com/_Zfbv3mHcYrc/SBPnJJcdt3I/AAAAAAAAAbs/hPVJdB1QqFE/s1600-h/bkafwideshot.JPG"><img id="BLOGGER_PHOTO_ID_5193748939628459890" style="MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="Thanks to Mike Hall for the photo" src="http://bp2.blogger.com/_Zfbv3mHcYrc/SBPnJJcdt3I/AAAAAAAAAbs/hPVJdB1QqFE/s320/bkafwideshot.JPG" border="0" /></a> <p>The actual talk went pretty well. There were around 30 people at the session (my session was concurrent with 3 other sessions). One of the highlights was the introduction where the hosts of .NET Rocks introduced me (via <a href="http://cid-8509553b6d92361d.skydrive.live.com/self.aspx/Moserware/bkaf_intro.wma">a recording</a>). Another highlight was being able to throw out flip-flops with <a href="http://www.inin.com/">my company's</a> logo on them to people in the audience that were first to answer some of the questions I asked.</p><p>In trying keep with the <a href="http://blogs.msdn.com/trobbins/archive/2004/12/12/280181.aspx">code camp manifesto</a>, I intentionally had no slides. The presentation was basically me stepping through this C# solution:</p><iframe style="BORDER-RIGHT: #dde5e9 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #dde5e9 1px solid; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 3px; BORDER-LEFT: #dde5e9 1px solid; WIDTH: 240px; PADDING-TOP: 0px; BORDER-BOTTOM: #dde5e9 1px solid; HEIGHT: 66px; BACKGROUND-COLOR: #ffffff" marginwidth="0" marginheight="0" src="http://cid-8509553b6d92361d.skydrive.live.com/embedrowdetail.aspx/Moserware/BetterKnowAFrameworkTalk.zip" frameborder="0" scrolling="no"></iframe><br /><br /><p>I created it to show how to use some lesser known classes and namespaces. I also briefly mentioned the "<a href="http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html">Turkey Test</a>" and its implications on code.</p><p>Feel free to download the solution and run through it. If you couldn't make it to the talk, feel free to ask questions via the comments. If you were able to attend the event in person, please fill out the <a href="http://www.codecampevals.com/">evaluation form online</a> or leave comments here as well. </p><p>Thanks to Aaron Lerch and many others who helped organize Indianapolis's first code camp! It was a privilege to get the chance to speak there.</p><p><b id="apz9">Appendix</b></p><p id="xj12">Here's a very brief recap of every "Better Know a Framework" segment since it started. If you'd like more information about it, I included a link to the show where you can listen to it. I also linked to the MSDN documentation for what was covered. I put an asterisk (*) by the show number if I covered that topic in my demo source file. </p><ul id="r_6-"><li id="naow"><a id="wb2h" title="243" href="http://www.dotnetrocks.com/default.aspx?showNum=243">243</a>* - <a id="nx8e" href="http://msdn2.microsoft.com/en-us/library/system.bitconverter.aspx">System.BitConverter</a>: Coverts value types like an int to bytes and back. Also determines endianness of the machine. <li id="r:1o"><a id="w216" title="244" href="http://www.dotnetrocks.com/default.aspx?showNum=244">244</a>* - <a id="oukr" href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.randomnumbergenerator.aspx">System.Security.Cryptography.RandomNumberGenerator</a>: Much better than System.Random at generating cryptographically strong random numbers. <li id="wbfu"><a id="m-rr" title="245" href="http://www.dotnetrocks.com/default.aspx?showNum=245">245</a> - <a id="euey" title="System.Net.NetworkInformation.Ping" href="http://msdn2.microsoft.com/en-us/library/system.net.networkinformation.ping.aspx">System.Net.NetworkInformation.Ping</a>: which returns a <a id="ul3y" title="System.Net.NetworkInformation.PingReply" href="http://msdn2.microsoft.com/en-us/library/system.net.networkinformation.pingreply.aspx">System.Net.NetworkInformation.PingReply</a> that has a <a id="nr5h" title="System.Net.NetworkInformation.IPStatus" href="http://msdn2.microsoft.com/en-us/library/system.net.networkinformation.ipstatus.aspx">System.Net.NetworkInformation.IPStatus</a> which is useful in determining if a remote machine is available (assuming they respond to ping that is). <li id="ri:s"><a id="qoij" title="246" href="http://www.dotnetrocks.com/default.aspx?showNum=246">246</a> - <a id="kvv4" title="System.Diagnostics.FileVersionInfo" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.fileversioninfo.aspx">System.Diagnostics.FileVersionInfo</a>: Useful for getting detailed information EXEs and DLLs (such as the company that produced the file). <li id="c24f"><a id="yeun" href="http://www.dotnetrocks.com/default.aspx?showNum=247">247</a>* - <a id="lyrh" title="System.Diagnostics.Process" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.aspx">System.Diagnostics.Process</a>: Information about a process on the system such as how much memory it's using, its process ID, main window name, etc. Also includes methods to do things like kill the process. <li id="a8g8"><a id="ktob" href="http://www.dotnetrocks.com/default.aspx?showNum=248">248</a> - <a id="aase" title="System.Net.Dns" href="http://msdn2.microsoft.com/en-us/library/system.net.dns.aspx">System.Net.Dns</a> Useful for determining the IP address(es) for a given host name. <li id="dcad"><a id="lvor" href="http://www.dotnetrocks.com/default.aspx?showNum=249">249</a>* - <a id="rhib" title="System.Text.StringBuilder" href="http://msdn2.microsoft.com/en-us/library/system.text.stringbuilder.aspx">System.Text.StringBuilder</a>: Much faster at building a string than concatenating a string. Discussed in depth on show #<a id="t4dw" title="87" href="http://www.dotnetrocks.com/default.aspx?showNum=87">87</a> <li id="taus"><a id="k_nu" href="http://www.dotnetrocks.com/default.aspx?showNum=250">250</a>* - <a id="nyes" title="System.Threading" href="http://msdn2.microsoft.com/en-us/library/system.threading.aspx">System.Threading</a> namespace: Classes useful in synchronization of threads: </li><ul id="g4l9"><li id="xq9n">CPU: <a id="nl_p" title="Interlocked" href="http://msdn2.microsoft.com/en-us/library/system.threading.interlocked.aspx">Interlocked</a> - Operations performed atomically by the processor (e.g. <a id="jptr" title="Interlocked.Increment" href="http://msdn2.microsoft.com/en-us/library/dd78zt0c.aspx"><br />Interlocked.Increment</a>) <li id="xqvn">CLR: <a id="t.3z" title="System.Threading.Monitor" href="http://msdn2.microsoft.com/en-us/library/system.threading.monitor.aspx">Monitor</a> and <a id="zcl1" title="ReaderWriterLock" href="http://msdn2.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx">ReaderWriterLock</a> <li id="xg7.">Kernel: <a id="qr:y" title="Semaphore" href="http://msdn2.microsoft.com/en-us/library/system.threading.aspx"><br />Semaphore</a>, <a id="chd4" title="AutoResetEvent" href="http://msdn2.microsoft.com/en-us/library/system.threading.autoresetevent.aspx"><br />AutoResetEvent</a>, <a id="bwpc" title="ManualResetEvent" href="http://msdn2.microsoft.com/en-us/library/system.threading.manualresetevent.aspx"><br />ManualResetEvent</a>, <a id="wegv" title="WaitHandle" href="http://msdn2.microsoft.com/en-us/library/system.threading.waithandle.aspx"><br />WaitHandle</a> (e.g. <a id="wbpk" title="WaitHandle.WaitAll" href="http://msdn2.microsoft.com/en-us/library/system.threading.waithandle.waitall.aspx"><br />WaitHandle.WaitAll</a>) </li></ul><li id="zbfv"><a id="a5-3" href="http://www.dotnetrocks.com/default.aspx?showNum=251">251</a>* -<a id="g:0b" title="System.IO.FileSystemWatcher" href="http://msdn2.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx"> System.IO.FileSystemWatcher</a>: Useful for getting notifications when something on the file system changes. <li id="cejc"><a id="j97o" href="http://www.dotnetrocks.com/default.aspx?showNum=252">252</a>* - <a id="vrqk" title="System.IO.Compression" href="http://msdn2.microsoft.com/en-us/library/system.io.compression.aspx">System.IO.Compression</a> namespace: Classes involved in compressing and decompressing files/streams. <li id="b-5v"><a id="m:.i" href="http://www.dotnetrocks.com/default.aspx?showNum=253">253</a>* - <a id="j9tx" title="System.Collections.Stack" href="http://msdn2.microsoft.com/en-us/library/system.collections.stack.aspx">System.Collections.Stack</a> for LIFO (last-in-first-out) and <a id="xx4z" title="System.Collections.Queue" href="http://msdn2.microsoft.com/en-us/library/system.collections.queue.aspx"><br />System.Collections.Queue</a> for FIFO (first-in-first-out). Also available are generic <a id="c345" title="Stack" href="http://msdn2.microsoft.com/en-us/library/3278tedw.aspx"><br />Stack<t></a> and <a id="dxcf" title="Queue" href="http://msdn2.microsoft.com/en-us/library/7977ey2c.aspx">Queue<t></a>. <li id="xx6i"><a id="ptyy" href="http://www.dotnetrocks.com/default.aspx?showNum=254">254</a> - <a id="or3m" title="System.ComponentModel.BooleanConverter" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.booleanconverter.aspx">System.ComponentModel.BooleanConverter</a>: Type converter to and from booleans. <li id="gzl9"><a id="i9c4" href="http://www.dotnetrocks.com/default.aspx?showNum=255">255</a> - Calendars in <a id="mzc7" title="System.Globalization" href="http://msdn2.microsoft.com/en-us/library/system.globalization.taiwancalendar.aspx">System.Globalization</a>: Many utilities for manipulating dates in various calendar schemes: </li><ul id="p4fn"><li id="szr6"><a id="s92." title="System.Globalization.GregorianCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.gregoriancalendar.aspx">GregorianCalendar</a> - (most popular) <li id="bs2:"><a id="q9q9" title="System.Globalization.HebrewCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.hebrewcalendar.aspx">HebrewCalendar </a><li id="j9q7"><a id="cg5c" href="http://msdn2.microsoftssystem.globalization.hijricalendar.aspx/">HijriCalendar</a> <li id="hc7u"><a id="xpnq" title="System.Globalization.JapaneseCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.japanesecalendar.aspx">JapaneseCalendar</a> <li id="ly0g"><a id="oegu" title="System.Globalization.JapaneseLunisolarCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.japaneselunisolarcalendar.aspx">JapaneseLunisolarCalendar</a> <li id="q-pk"><a id="ssuy" title="System.Globalization.JulianCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.juliancalendar.aspx">JulianCalendar</a> <li id="zmge"><a id="cskg" title="System.Globalization.KoreanCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.koreancalendar(VS.71).aspx">KoreanCalendar</a> <li id="gbz0"><a id="nqfj" title="System.Globalization.PersianCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.persiancalendar.aspx">PersianCalendar</a> <li id="fxo2"><a id="zr43" title="TaiwanCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.taiwancalendar.aspx">TaiwanCalendar</a> <li id="tmz1"><a id="egn2" title="ThaiBuddhistCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.thaibuddhistcalendar.aspx">ThaiBuddhistCalendar</a> <li id="pwep"><a id="ldin" title="UmAlQuraCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.umalquracalendar.aspx">UmAlQuraCalendar</a> <li id="dqqk"><a id="i3lh" title="EastAsianLunisolarCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.eastasianlunisolarcalendar.aspx">EastAsianLunisolarCalendar</a> <li id="g:qu"><a id="dlzh" title="ChineseLunisolarCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.chineselunisolarcalendar.aspx">ChineseLunisolarCalendar</a> </li></ul><br /><li id="zsyx"><a id="wv.u" href="http://www.dotnetrocks.com/default.aspx?showNum=256">256</a> - <a id="bmlf" title="System.Web.Mail" href="http://msdn2.microsoft.com/en-us/library/system.web.mail.aspx">System.Web.Mail</a>: Old (deprecated) way of sending an email. <li id="p-.6"><a id="zajk" href="http://www.dotnetrocks.com/default.aspx?showNum=257">257</a> - <a id="mx6k" title="System.Net.Mail" href="http://msdn2.microsoft.com/en-us/library/system.net.mail.aspx">System.Net.Mail</a>: .net 2.0+ way of sending emails <li id="dg7w"><a id="lqzs" href="http://www.dotnetrocks.com/default.aspx?showNum=258">258</a>* - <a id="j7bh" title="System.ComponentModel.BackgroundWorker" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx">System.ComponentModel.BackgroundWorker</a>: Simplifies use of background worker threads that need to update a UI via use of the <a id="gx5e" title="RunWorkAsync" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.backgroundworker.runworkerasync.aspx">RunWorkAsync</a> method and <a id="rggc" title="DoWork" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.backgroundworker.dowork.aspx">DoWork</a> event. <li id="oz5x"><a id="p2sg" href="http://www.dotnetrocks.com/default.aspx?showNum=259">259</a> - <a id="pixh" title="System.ComponentModel.BrowseableAttribute" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.browsableattribute.aspx">System.ComponentModel.BrowseableAttribute<br /></a>: Can be used to disable a property's visibility in the properties window (e.g. windows forms control). <li id="q2ed"><a id="jv0u" href="http://www.dotnetrocks.com/default.aspx?showNum=260">260</a>* - <a id="u9ut" title="System.Collections.Generic.Dictionary" href="http://msdn2.microsoft.com/en-us/library/xfhwa508.aspx">System.Collections.Generic.Dictionary<tkey,></a>: Maps keys to values <li id="u_si"><a id="nsjs" href="http://www.dotnetrocks.com/default.aspx?showNum=261">261</a> - <a id="jx1h" title="System.Windows.Input" href="http://msdn2.microsoft.com/en-us/library/system.windows.input.aspx">System.Windows.Input</a> namespace: WPF classes used for input (e.g. <a id="ob0b" title="InputManager" href="http://msdn2.microsoft.com/en-us/library/system.windows.input.notifyinputeventargs.inputmanager.aspx"><br />InputManager</a>, <a id="bw4b" title="KeyboardNavigation" href="http://msdn2.microsoft.com/en-us/library/system.windows.input.keyboardnavigation.aspx">KeyboardNavigation</a>, <a id="uyyj" title="Mouse" href="http://msdn2.microsoft.com/en-us/library/system.windows.input.keyboardnavigation.aspx">Mouse</a>) <li id="avuw"><a id="of:0" href="http://www.dotnetrocks.com/default.aspx?showNum=262">262</a> - <a id="zpir" title="System.Reflection.Assembly" href="http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.aspx">System.Reflection.Assembly</a>: Useful for finding information about .net assemblies such as classes, interfaces, methods, properties, events, etc. <li id="su3."><a id="wv6n" href="http://www.dotnetrocks.com/default.aspx?showNum=263">263</a>* - <a id="cxzt" title="System.Threading.Timer" href="http://msdn2.microsoft.com/en-us/library/system.threading.timer.aspx">System.Threading.Timer</a>: Simple and lightweight timer. See <a id="nqyu" title="this link" href="http://shrinkster.com/rv3">comparison</a> of timers. <li id="kd4t"><a id="lyyn" href="http://www.dotnetrocks.com/default.aspx?showNum=264">264</a> - <a id="z-qj" title="System.SerializableAttribute" href="http://msdn2.microsoft.com/en-us/library/system.serializableattribute.aspx">System.SerializableAttribute</a>: Marks an object as serializable (able to create a persisted represention of it). A binary formatter/serializer is at <a id="rd.0" title="System.Runtime.Serialization.Formatters.Binary.BinaryFormatter" href="http://msdn2.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx"><br />System.Runtime.Serialization.Formatters.Binary.BinaryFormatter</a> <li id="auuo"><a id="u439" href="http://www.dotnetrocks.com/default.aspx?showNum=265">265</a> - <a id="kcs8" title="System.Xml.XPath.XPathDocument" href="http://msdn2.microsoft.com/en-us/library/system.xml.xpath.xpathdocument.aspx">System.Xml.XPath.XPathDocument</a>: Provides a fast read-only in-memory representation of an XML document using the XPath data model. See also <a id="p-ni" title="System.Xml.XmlReader" href="http://msdn2.microsoft.com/en-us/library/system.xml.xpath.xpathdocument.aspx"><br />System.Xml.XmlReader</a> for read-only XML reading. <li id="g.:7"><a id="n8gx" href="http://www.dotnetrocks.com/default.aspx?showNum=266">266</a> - <a id="l1pp" title="System.ApplicationException" href="http://msdn2.microsoft.com/en-us/library/system.applicationexception.aspx">System.ApplicationException</a>: Intended for use of application specific exceptions, but if you read <a id="ueug" title="Best Practices for Handling Exceptions" href="http://msdn2.microsoft.com/en-us/library/seyhszts.aspx">Best Practices for Handling Exceptions</a>, you'll see that you shouldn't use it anymore. <li id="omf."><a id="eid9" href="http://www.dotnetrocks.com/default.aspx?showNum=267">267</a>* - <a id="jla0" title="Global Assembly Cache" href="http://msdn2.microsoft.com/en-us/library/yf1d93sz.aspx">Global Assembly Cache</a>: Otherwise known as the GAC. Provides a system-wide storage facility for assemblies. To put an assembly in the GAC, you need to use the <a id="bmoh" title="strong name tool" href="http://msdn2.microsoft.com/en-us/library/k5b5tt23.aspx"><br />strong name tool</a> (SN) to get it ready, and then use <a id="vu1b" title="GACUTIL" href="http://msdn2.microsoft.com/en-us/library/ex0ss12c.aspx"><br />GACUTIL</a> on it. <li id="a5yl"><a id="oz8-" href="http://www.dotnetrocks.com/default.aspx?showNum=268">268</a>* - <a id="at:k" title="System.Console" href="http://msdn2.microsoft.com/en-us/library/system.console.aspx">System.Console</a>: Besides the obvious methods like <a id="b07s" title="WriteLine" href="http://msdn2.microsoft.com/en-us/library/system.console.writeline.aspx">WriteLine</a>, there are many lesser-known ones: </li><ul id="lub3"><li id="mufs"><a id="n1i6" title="CapsLock" href="http://msdn2.microsoft.com/en-us/library/system.console.capslock.aspx">CapsLock</a> <li id="x0z-"><a id="orpi" title="NumberLock" href="http://msdn2.microsoft.com/en-us/library/system.console.numberlock.aspx">NumberLock</a> <li id="nz3m"><a id="bzh_" title="ForegroundColor" href="http://msdn2.microsoft.com/en-us/library/system.console.numberlock.aspx">ForegroundColor</a> <li id="ihot"><a id="oqnd" title="WindowHeight" href="http://msdn2.microsoft.com/en-us/library/system.console.windowheight.aspx">WindowHeight</a> <li id="wak4"><a id="d0.h" title="WindowTop" href="http://msdn2.microsoft.com/en-us/library/system.console.windowtop.aspx">WindowTop</a> <li id="s4wp"><a id="ezbq" title="WindowLeft" href="http://msdn2.microsoft.com/en-us/library/system.console.windowleft.aspx">WindowLeft</a> <li id="if:3"><a id="j_:o" title="WindowWidth" href="http://msdn2.microsoft.com/en-us/library/system.console.windowwidth.aspx">WindowWidth</a> <li id="yiih"><a id="fmu_" title="Title" href="http://msdn2.microsoft.com/en-us/library/system.console.title.aspx">Title</a> (sets what to display in the title bar) <li id="g7ns"><a id="r_w:" title="CursorVisible" href="http://msdn2.microsoft.com/en-us/library/system.console.cursorvisible.aspx">CursorVisible</a> <li id="gr.w"><a id="l.iq" title="In" href="http://msdn2.microsoft.com/en-us/library/system.console.in.aspx">In</a> (Stdin) <li id="b:sr"><a id="zq1q" title="Error" href="http://msdn2.microsoft.com/en-us/library/system.console.error.aspx">Error</a> (Stderr) <li id="dck8"><a id="cgss" title="Out" href="http://msdn2.microsoft.com/en-us/library/system.console.out.aspx">Out</a> (Stdout) <li id="xh:n"><a id="s_vy" title="CursorSize" href="http://msdn2.microsoft.com/en-us/library/system.console.cursorsize.aspx">CursorSize</a> <li id="l7ni"><a id="vlmf" title="CursorLeft" href="http://msdn2.microsoft.com/en-us/library/system.console.cursorleft.aspx">CursorLeft</a> <li id="j187"><a id="sn3x" title="CursorTop" href="http://msdn2.microsoft.com/en-us/library/system.console.cursortop.aspx">CursorTop</a> <li id="po1j"><a id="tiu8" title="BackgroundColor" href="http://msdn2.microsoft.com/en-us/library/system.console.backgroundcolor.aspx">BackgroundColor</a><br /></li></ul><li id="jxtb"><a id="w45:" href="http://www.dotnetrocks.com/default.aspx?showNum=269">269</a>* - <a id="a33f" title="System.Environment" href="http://msdn2.microsoft.com/en-us/library/system.environment.aspx">System.Environment</a>: Contains many assorted details about your application's environment: </li><ul id="v2g:"><li id="lfzl"><a id="qvh0" title="UserName" href="http://msdn2.microsoft.com/en-us/library/system.environment.username.aspx">UserName</a>: User name of the person currently logged in. <li id="wmhs"><a id="graf" title="WorkingSet" href="http://msdn2.microsoft.com/en-us/library/system.environment.workingset.aspx">WorkingSet</a>: Physical memory mapped to the process <li id="fyfr"><a id="xfpd" title="GetFolderPath" href="http://msdn2.microsoft.com/en-us/library/system.environment.getfolderpath.aspx">GetFolderPath</a>: Useful for finding file paths to things like the Program Files folder (which can be different depending on if you're running 64 bit Windows) </li></ul><br /><li id="woys"><a id="hg4t" href="http://www.dotnetrocks.com/default.aspx?showNum=270">270</a> - <a id="rg1a" title="System.Net.HttpWebRequest" href="http://msdn2.microsoft.com/en-us/library/system.net.httpwebrequest.aspx">System.Net.HttpWebRequest </a>, <a id="hipr" title="HttpWebResponse" href="http://msdn2.microsoft.com/en-us/library/system.net.httpwebresponse.aspx">HttpWebResponse </a>, <a id="nrfk" title="WebRequest" href="http://msdn2.microsoft.com/en-us/library/system.net.webrequest.aspx">WebRequest </a>classes: Lower level classes used to perform an HTTP request. See notes on show #<a id="hea5" title="275" href="http://www.dotnetrocks.com/default.aspx?showNum=275">275</a> for the much simpler WebClient class. <li id="zs_2"><a id="w8ed" href="http://www.dotnetrocks.com/default.aspx?showNum=271">271</a>* - <a id="g6o0" title="System.IO.StreamWriter" href="http://msdn2.microsoft.com/en-us/library/system.io.streamwriter.aspx">System.IO.StreamWriter</a> and <a id="r8al" title="StreamReader" href="http://msdn2.microsoft.com/en-us/library/system.io.streamreader.aspx">StreamReader</a>: Helper classes for dealing with text files/streams (contains methods like <a id="nens" title="ReadToEnd" href="http://msdn2.microsoft.com/en-us/library/system.io.streamreader.readtoend.aspx">ReadToEnd</a>() for returning a string of whatever is left in the stream) <li id="bnmw"><a id="zthf" href="http://www.dotnetrocks.com/default.aspx?showNum=272">272</a> - <a id="fn65" title="System.Windows.Forms.Splitter" href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.splitter.aspx">System.Windows.Forms.Splitter</a>: Control that allows you to split parts of a UI in a way that allows the user to expand or shrink an area. This class can be hard to use, see show #<a id="i-nf" title="273" href="http://www.dotnetrocks.com/default.aspx?showNum=273">273</a>. <li id="c_lc"><a id="w4ix" href="http://www.dotnetrocks.com/default.aspx?showNum=273">273</a> - <a id="aryk" title="System.Windows.Forms.SplitContainer" href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.splitcontainer.aspx">System.Windows.Forms.SplitContainer</a>: Much simpler way to provide a split UI. <li id="pazx"><a id="e7sn" href="http://www.dotnetrocks.com/default.aspx?showNum=274">274</a> - <a id="azq1" title="System.Windows.Forms.ToolTip" href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.tooltip.aspx">System.Windows.Forms.ToolTip</a>: An <a id="nk8g" title="extender provider" href="http://msdn2.microsoft.com/en-us/library/ms171836.aspx"><br />extender provider</a> that allows you to add Tooltips to all items in a container's scope. It implements <a id="s.10" title="System.ComponentModel.IExtenderProvider" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.iextenderprovider.aspx">System.ComponentModel.IExtenderProvider</a>. Similiar to how <a id="g:ci" title="System.Windows.Forms.ErrorProvider" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.iextenderprovider.aspx"><br />System.Windows.Forms.ErrorProvider</a> works. <li id="etbx"><a id="tm2x" href="http://www.dotnetrocks.com/default.aspx?showNum=275">275</a>* - <a id="mkns" title="System.Net.WebClient class" href="http://msdn2.microsoft.com/en-us/library/system.net.webclient.aspx">System.Net.WebClient</a>: Provides a very easy way to perform common HTTP operations in 1 line of code (e.g. <a id="etog" title="DownloadFile" href="http://msdn2.microsoft.com/en-us/library/system.net.webclient.downloadfile.aspx">DownloadFile</a>, <a id="la-s" title="DownloadData" href="http://msdn2.microsoft.com/en-us/library/system.net.webclient.downloaddata.aspx">DownloadData</a>) <li id="i2h9"><a id="yxwn" href="http://www.dotnetrocks.com/default.aspx?showNum=276">276</a> - <a id="ka9q" title="System.Web.UI.Page" href="http://msdn2.microsoft.com/en-us/library/system.web.ui.page.aspx">System.Web.UI.Page</a>: <a id="td5y" title="SavePageStateToPersistenceMedium" href="http://savepagestatetopersistencemedium/">SavePageStateToPersistenceMedium</a> and <a id="ctl00_rs1_mainContentContainer_ctl367" href="http://msdn2.microsoft.com/en-us/library/system.web.ui.page.loadpagestatefrompersistencemedium.aspx"><br />LoadPageStateFromPersistenceMedium</a> allows you to store viewstate in a different place besides sending it down to the browser each time. This can be useful as viewstate can account for a large (67%+) part of your page's size. <li id="mue4"><a id="m33b" href="http://www.dotnetrocks.com/default.aspx?showNum=277">277</a> - <a id="a8wa" title="System.Web.Management" href="http://msdn2.microsoft.com/en-us/library/system.web.management.aspx">System.Web.Management</a> namespace: Classes that do all sorts of management of web servers and web farms. For example, <a id="ctl00_rs1_mainContentContainer_ctl65" href="http://msdn2.microsoft.com/en-us/library/system.web.management.webauditevent.aspx">WebAuditEvent</a> allows you to audit web events. <li id="dy6."><a id="az_7" href="http://www.dotnetrocks.com/default.aspx?showNum=278">278</a> - <a id="mzr5" title="System.IO.IsolatedStorage" href="http://msdn2.microsoft.com/en-us/library/system.io.isolatedstorage.aspx">System.IO.IsolatedStorage</a>: (In this show Carl thought that IsolatedStorage was used for storing things in a secret way. See show #<a id="os_:" title="278" href="http://www.dotnetrocks.com/default.aspx?showNum=278">278</a> ) <li id="kckd"><a id="d2_9" href="http://www.dotnetrocks.com/default.aspx?showNum=279">279</a>* - Christopher Loaf from Sweden pointed out that <a id="mzr5" title="System.IO.IsolatedStorage" href="http://msdn2.microsoft.com/en-us/library/system.io.isolatedstorage.aspx">System.IO.IsolatedStorage</a> is primarily used for storing and retrieving data in a partial trust environment (e.g. a web browser). <li id="p1vp"><a id="gyqs" href="http://www.dotnetrocks.com/default.aspx?showNum=280">280</a>* - <a id="vyof" title="System.Convert" href="http://msdn2.microsoft.com/en-us/library/system.convert.aspx">System.Convert</a>: Methods for converting items from one type to another (e.g <a id="kfuk" title="ToBoolean" href="http://msdn2.microsoft.com/en-us/library/system.convert.toboolean.aspx"><br />ToBoolean</a>, <a id="fxps" title="ToChar" href="http://msdn2.microsoft.com/en-us/library/system.convert.tochar.aspx">ToChar</a>, <a id="zhs7" title="ToBase64String" href="http://msdn2.microsoft.com/en-us/library/system.convert.tobase64string.aspx">ToBase64String</a>, <a id="vbt8" title="FromBase64String" href="http://msdn2.microsoft.com/en-us/library/system.convert.frombase64string.aspx">FromBase64String</a>). In addition, has <a id="k2th" title="IsDBNull" href="http://msdn2.microsoft.com/en-us/library/system.convert.isdbnull.aspx">IsDBNull</a> to determine if an object is a database null value. <li id="tlnm"><a id="yn1s" href="http://www.dotnetrocks.com/default.aspx?showNum=281">281</a>* <a id="x.f2" title="System.Globalization.CultureInfo" href="http://msdn2.