Building Domain Specific Languages in Boo on the .NET Platform#

Ayende Rahien will be giving a course on buliding DSLs with Boo in Austin on May 19-20. I'm a closet fan of Boo, having lurked on the mailing list for about 6 months, and really looking forward to getting a stronger grasp of the language, and the benefits of building your own domain specific languages. This is a great opportunity to learn from the preeminent creator of Boo DSLs.

Scott Bellware sent a good writeup to the AgileATX mailing list:

This class takes you deeper into the reasoning and power of dynamic
programming on the CLR.  It will show you how to build and take
advantage of DSL's for your own CLR applications, and why DSL's and
language-oriented programming are such a valuable practice at this
point on the programming timeline. 
You'll leave this class having been jump-started on a new, powerful
language and paradigm, and be connected to other motivated .NET folks
who are working toward bringing some of successes of dynamic
programming communities into the .NET community.

The class will also give you the opportunity to check out a town that
folks are starting to recognize as a progressive and leading .NET
competency in North America, and to have some fun with Austin's
developer community folks in lush green and sunshine of Central Texas.

There are still some spots open, if you are interested you can register here.

.NET | Boo
Saturday, May 10, 2008 9:45:43 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

The power of yield (return)#

Yield is one of the coolest, yet underused, new .NET 2.0 features that you may not be familiar with. Yes, I'm talking about a 2.0 feature - even though 3.5 just came out, it is my experience that a large number of developers have still not embraced all that 2.0 gave us. Hopefully this article will help make this powerful, yet initially confusing, feature more approachable.

Some background facts

When you "foreach" over an object (array, collection, etc), it must implement IEnumerable or IEnumerable<T> - the generic version which returns strongly typed objects (for the rest of this article, I'll just refer to IEnumerable).

All arrays, and most collections (ArrayList, List<T>) implement IEnumerable, which is why you can "foreach" over them.

If ALL you need to do to a collection is cycle through its members - you only need to reference it as an IEnumerable. That explains why the following code is perfectly valid:

IEnumerable<int> numbers = new int[] { 1, 2, 3 }; foreach (int i in numbers) { Console.WriteLine(i); }

It is always better to depend on abstract types (interfaces, abstract base classes) rather than concrete types. This allows you to change the implementation of a method without impacting any of its callers.

Consider this example where CallingMethod gets a set of numbers from MethodBeingCalled. It really doesn't care if it gets an array or a List or whatever. It just does a foreach over it, which means it only needs the functionality exposed by the IEnumerable interface.

public void CallingMethod() { List<int> numbers = MethodBeingCalled(); foreach (int i in numbers) { Console.WriteLine(i); } } private List<int> MethodBeingCalled() { List<int> numbers = new List<int>(); numbers.AddRange(new int[] { 1, 2, 3 }); return numbers; }

The problem with the current design is that the CallingMethod declares the list of numbers List<int>. That is a specific implementation detail. If CallingMethod needed to add more numbers to the list after it was returned from MethodBeingCalled, or if individual numbers were being accessed by their index, then it would make sense to declare it as a List<T> (or better, IList<T>). But it really only needs to cycle through the numbers in order. If MethodBeingCalled wanted to change its implementation to return an int[] instead, it would have to change its signature, and CallingMethod would also have to change. However, if CallingMethod had just declared its local variable as IEnumerable<int> (because that is the only functionality it truly depends on), then it would not have to change if MethodBeingCalled changes - as long as it still returns something that implements IEnumerable<int>.

So what does foreach do? It asks the IEnumerable if it has any items. If so, it gets the next item and uses it within the loop. It then asks the IEnumerable again if it has more items, gets the next one, and so on, until there are no more items. The important thing to note here is that foreach never works with the entire collection all it once - it only deals with one item at a time.

Introducing yield

How can we use all of this information? If you have a method that returns a collection of data, and you can be sure that callers are only going to be interested in looping over each item in the collection, one at a time (which is very common), you can declare your method's return value as IEnumerable<T>.

When you declare your method's return value as IEnumerable<T>, something magic happens: the C# compiler will now let you use the yield keyword within the body! So why does that matter? Because it allows you to take advantage of the way that foreach really works. Remember, foreach will just ask for one value at a time. When it does, it will call into your method - your method will run until it encounters a yield return statement. When it reaches a yield return statement, that value is immediately returned to the caller. In the next iteration of the caller's loop, it will ask again if there is another value, your method will start executing again, but this time it will start on the line after the last yield statement that was run. Yes, you read that right: execution alternates between the calling method and the method being called, all the way through the loop. This is completely different from the normal way that methods interact, where one method gives up control to another method, which doesn't return until it is completely finished executing.

This has at least 2 very important implications for the method that returns the IEnumerable<T>:
1) It does not need to build up a big list of all of the items it plans to return, holding them all in memory at the same time. If the list of items is very large, holding them all in memory at once can be a significant burden.

2) It does not necessarily need to do the work to produce all of the items in the list. If the caller breaks out of the foreach loop before the entire collection has been traversed - all of the work needed to produce the remaining items in the colleciton is avoided. Without using the yield keyword, you would have to build up the entire collection to return, even if the caller was only going to look at the first few items.

Demonstration

To illustrate the advantage of this approach, I included sample code at the bottom. You can create a new Console Application and paste this over the default Program.cs.

A method, GetCombinations returns a collection of 2 numbers combined. The caller then loops through the collection, looking for a specific combination: "13".

First, run it using GetCombinations. This is implemented the way most people would write a method that returns a collection, in .NET 1.1. The output willl look something like this (the indented output is from within GetCombinations):

BEFORE call to GetCombinations
        Beginning execution of GetCombinations
        Producing 33
        Producing 23
        Producing 13
        Producing 32
        Producing 22
        Producing 12
        Producing 31
        Producing 21
        Producing 11
        Ending execution of GetCombinations
AFTER call to GetCombinations
Checking 33
Checking 23
Checking 13
Found!
Elapsed: 00:00:08.9931583

Now, comment out the line that calls GetCombinations, and uncomment the line that calls BetterGetCombinations. It is important to note that BetterGetCombinations uses the exact same algorithm as GetCombinations - given the same input, they will both return the exact same list of strings, in the same order (I've emphasized the lines that changed, in the sample code below). But since the caller is only looking for a specific combination, not all combinations need to be produced. Consider the output:

BEFORE call to GetCombinations
AFTER call to GetCombinations
        Beginning execution of BetterGetCombinations <-- notice that BetterGetCombinations doesn't really start until the foreach loop - NOT when the method was first called!

        Producing 33
Checking 33
        Producing 23
Checking 23
        Producing 13
Checking 13
Found!
Elapsed: 00:00:02.9976438

With the improved implementation that took advantage of the yield keyword, the program was able to finish its job in less than half the time! It also used much less memory, as it never had to store all 9 strings in a collection. Now imagine the potential impact if GetCombinations returned a collection with thousands of entries!

Sample Code

Paste the code below over the default Program.cs in a new Console Application:

using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; namespace YieldDemo { class Program { static void Main() { Stopwatch timer = Stopwatch.StartNew(); Console.WriteLine("BEFORE call to GetCombinations"); //1) First try running using the GetCombinations that returns a List<string> List<string> combinations = GetCombinations(3, 3); //2) After observing the output, comment out the above line, uncomment the next line, and re-run // IEnumerable<string> combinations = BetterGetCombinations(3, 3); Console.WriteLine("AFTER call to GetCombinations"); foreach (string combination in combinations) { Console.WriteLine("Checking " + combination); if (combination == "13") { Console.WriteLine("Found!"); break; } } timer.Stop(); Console.WriteLine("Elapsed: " + timer.Elapsed); } static List<string> GetCombinations(int left, int right) { Console.WriteLine("\tBeginning execution of GetCombinations"); List<string> output = new List<string>(); int currentLeft; int currentRight = right; while (currentRight > 0) { currentLeft = left; while (currentLeft > 0) { string newCombinationToProduce = currentLeft.ToString() + currentRight; Console.WriteLine("\tProducing " + newCombinationToProduce); Thread.Sleep(1000); // simulate expensive process to produce a combination output.Add(newCombinationToProduce); --currentLeft; } --currentRight; } Console.WriteLine("\tEnding execution of GetCombinations"); return output; } static IEnumerable<string> BetterGetCombinations(int left, int right) { Console.WriteLine("\tBeginning execution of BetterGetCombinations"); // NOTE The local List is not necessary in this implementation int currentLeft; int currentRight = right; while (currentRight > 0) { currentLeft = left; while (currentLeft > 0) { string newCombinationToProduce = currentLeft.ToString() + currentRight; Console.WriteLine("\tProducing " + newCombinationToProduce); Thread.Sleep(1000); // simulate expensive process to produce a combination yield return newCombinationToProduce; // insteading of adding to a list, just return the value --currentLeft; } --currentRight; } Console.WriteLine("\tEnding execution of BetterGetCombinations"); } } }
Sunday, February 03, 2008 12:02:09 PM (Central Standard Time, UTC-06:00) #    Comments [17]  | 

 

ALT.NET heart Microsoft#

So a high profile ALT.NETter, who is not in attendance at this weekend's altnetconf, has decided he no longer wants to be associated with the group because of its perceived negativity. It is a shame he wasn't here in person to experience the bizarro-world like ending to Day 2. The closing remarks, which is a chance for anyone in attendance to stand and share their thoughts on the day, were composed entirely of expressions of excitement around the just demonstrated System.Web.MVC framework, and thanks and appreciation to the Microsoft ASP.NET team that created it. This is not an easy crowd to please, but mostly because we all want to be able to assert our preference of tools and practices individually. NOT because we want to use "anything but Microsoft", but because we want to be able to choose "some things that are not from Microsoft". When Microsoft does provide a great tool (as they did with the .NET Framework, and potentially the MVC framework) members of the crowd are willing embrace it. Now, we are not a hive mind (a fact which seems to be frustrating some people that want us to come to some kind of consensus... on anything), so I won't say everyone is excited about it. But unlike the earlier opening remarks, at the end nobody stood up to air their grievances with Microsoft. It was all smiles and love for Scott Guthrie (who was there demonstrating the framework and representing the ASP.NET team). Yes, even from Scott Bellware.

(Of course, it may all be a side effect of ScottGu's super-hero power of being able to foster man-crush's from entire rooms of ornery, cynical developers.)

Technorati Tags:
Saturday, October 06, 2007 8:13:13 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

ALT.NET is freedom#

It seems to me that a lot of the confusion and/or distaste around the ALT.NET name stems from people associating it with the alternative rock movement from the early 90s. Of course that term was always grating from the beginning, and now that the fad is over, its even harder to take seriously.

I have no idea if "alternative programming"  is what David Laribee had in mind when he coined it, but it certainly wasn't my first thought. I am, after all, a computer geek first, and a domesticated recovering punk rock skate rat a distant second. As a computer geek, when I see the words "alt dot something", I think of the Usenet hierarchy specifically dedicated to the free thinking and exchange of ideas:

All other Usenet hierarchies require you to follow a definite procedure to create a new group in that category. However, a newsgroup in the alt hierarchy can be created by anyone. The resulting set of newsgroups form a truly global democratic system, since each group in the alt category survives only if people show an interest in it.

To me, alt.net is about the freedom of developers to choose the tools and processes that bring them joy and get the job done. They are not constrained by the choices offered by a single vendor (Microsoft), just like backers of the alt Usenet groups were not constrained by the policies of the central backbone administrators.

Jeffrey Palermo wants to qualify the term to give it a more concrete definition. While I don't have a problem with what it means to him, I don't think it needs it. If you want to consider yourself part of the "alt.net" movement, you are. If you don't, well, you might be anyway. Any sort of checklist that attempts to define it any further will just succeed in creating a new set of artificial "backbone administrators" that some will inevitably find too constraining.

The idea of the alt. Usenet hierarchy is much bigger than just offering a place to talk about sex and drugs. It is offering a place to talk about Anything. Similarly, ALT.NET is much bigger than wanting to practice BDD or use NHibernate. It is about thinking freely within a community that previously never realized it could.

Sunday, September 23, 2007 11:04:08 PM (Central Standard Time, UTC-06:00) #    Comments [1]  | 

 

Firefox error resolved: One or more files could not be updated#

I have automatic updates enabled in Firefox. For my day-to-day work, I run as a non-administrator user in Windows XP. I need to log in as an administrator whenever I want to install new software - including updates for Firefox.

The problem is that Firefox is not content to just update all necessary files when you are logged in as the administrator. When you return to your non-admin account and launch Firefox, you may be greeted with the following message:

"One or more files could not be updated. Please make sure all other applications are closed and that you have permission to modify files, and then restart Firefox to try again."

You can click through the message, and Firefox will launch anyway. Okay, I guess the updates weren't that important and I can ignore the message. However, the next time I launch Firefox, and am again prompted and again click through it. It seems I am doomed to launching Firefox with two clicks for all eternity.

Of course I searched the internet for the error message, but nothing very fruitful came of it. Apparently the error has a number of different causes. I did find some others reporting the problem when run as a non-administrator, but the solution was always "just run as administrator" or "elevate your rights".

I finally solved the problem without changing any rights for my user account, and am now posting it here in hopes that others will find it useful.

UPDATE: Based on suggestions in the comments, I've started using a much simpler method. If you have an administrator password, you can run the following command in a Command Prompt:

runas /user:Administrator /noprofile /env "C:\Program Files\Mozilla Firefox\firefox.exe"

The rest of this article is unnecessary if you want to follow this "delete the updates folder" approach.

Note: you must be able to log in as an administrator on the computer, but your primary user account does not have to be an administrator.

Pre-requisite: As an administrator, download and install Process Monitor from Sysinternals/Microsoft.

  1. Close all running instances of Firefox.
  2. Open an Administrator command prompt by right-clicking on a Command Prompt icon, choose Run As... and enter the credentials of a user with administrator rights.
  3. Launch Process Monitor from the administrator command prompt by typing the full path to the executable (wherever you installed it). For example: c:\apps\procmon.exe (tab completion can be very helpful for this step).
  4. Within Process Monitor, turn off "Show Registry Activity" and "Show File System Activity" from the toolbar. Only "Show Process and Thread Activity should be enabled". This step is not absolutely necessary, but it will eliminate a lot of extra noise.
  5. Start Firefox, and click through the "Software Update Failed" dialog until the browser opens.
  6. Switch back to Process Monitor and press CTRL-E or the click the toolbar button to stop capturing events. Close any Firefox windows that might be open.
  7. Scroll through the list of processes and double-click on the first instance of "updater.exe" (it should have the value "Process Start" in the Operation column). Switch to the Process tab of the Event Properties window that opens.
  8. Select the entire contents of the "Command Line:" textbox and copy it (CTRL-C or right-click, Copy). It should look something like this (all one line): "C:\Documents and Settings\Josh\Local Settings\Application Data\Mozilla\Firefox\Mozilla Firefox\updates\0\updater.exe" "C:\Documents and Settings\Josh\Local Settings\Application Data\Mozilla\Firefox\Mozilla Firefox\updates\0" "3824" "C:\Program Files\Mozilla Firefox" "C:\Program Files\Mozilla Firefox\firefox.exe"
  9. Switch back to the administrator command prompt and right-click, Paste to paste the command-line. Press Enter.
  10. You should see a dialog indicating that Firefox is updating. Close the browser that opens since it is still running as the administrator.
  11. Now open Firefox normally. It should start up without the annoying error message.

I'm not sure if the command-line from step 8 is always the same (the "3824" is the only part I can imagine would vary). If it is always the same, you can save a lot of steps on subsequent updates by just creating a batch file with that command and running it as administrator. If anyone has any insight to the parameters of this command, let me know.

Sunday, June 10, 2007 6:38:07 PM (Central Standard Time, UTC-06:00) #    Comments [29]  | 

 

All content © 2008, Joshua Flanagan
About this site
Send mail to the author(s) Contact me
Feed your aggregator (RSS 2.0)
Joshua Flanagan
I have been developing software professionally for 10 years; focusing on .NET since its release. I use this site to interact with, and contribute to, the .NET software development community.
Microsoft Certified Application Developer

On this page
Archives
Rest of the world

Acknowledgements

Powered by: newtelligence dasBlog 1.9.7170.677

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Site theme based on the essence design by Jelle Druyts