Tuesday, June 30, 2009
AddFromTemplate has misleading documentation
The documentation for this method says this about the project name parameter:
"The name of the project file in the destination directory. This should include the extension."
Seems pretty clear about whether or not to include the extension, right?
The first version of our wizard included the extension. Unfortunately, this resulted in the $safeprojectname$ parameter ending up with the extension in it as well. Since this parameter is also used to define the default namespace, we ended up with test classes whose full names were something like MyApplication.MyProjectTests.csproj.MyClassTests. Yuck.
The solution appears to be to completely disregard the documentation and don't include the extension. So far this appears to be working.
Wednesday, June 03, 2009
How to access a Virtual PC from the Host
This took some digging to find, but this article was exceptionally helpful. The only extra step I had to take was to disable Windows Firewall on the virtual machine so it would let the network traffic through.
Wednesday, April 15, 2009
SSRS 2005 in Vista with IIS 7
While poking around the IIS Management tool I noticed that in the Http Handlers section, virtually nothing was listed for the ReportServer web application. No ASP.NET, no nothing. I clicked "Revert to Inherited", causing it to pick up the settings of the parent site (that had ASP.NET enabled), and everything started working fine. Who knows how the handlers got overridden, but at least it's working now.
EDIT: Also, to fix some other nastiness, you have to follow the advice of "rmeans" here
Without the wildcard mapping you get a fun "For security reasons DTD is prohibited in this XML document" error.
EDIT2: And to actually call the web services via WCF you have to take the obvious step of switching the generated basicHttpBinding to pass the windows credentials, like this:
<binding name="ReportingService2005Soap" ... >
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
but also the totally not obvious step of allowing the client credentials to impersonate, even if you're using a shared data source with a defined id and all that. You add a behavior to the endpoint for the SSRS web service like this:
<endpointBehaviors>
<behavior name="allowImpersonate">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
Saturday, April 11, 2009
Writing a Compiler with F# Part 4
Now that we've defined the AST for our language and written a simple evaluator, let's make it easier to construct ASTs. Obviously we don't create C# programs by directly constructing the syntax trees; instead, we type in text which is lexed and then parsed into the tree.
It turns out that creating lexers and parsers is such a common language task that there are many tools available to generate them for us from some basic definitions. One common lexer generator is called Lex and F# ships with a version of it called fslex. Likewise, fsyacc is the F# variant of the Yacc parser generators. I'm not going to talk about the different types of grammars as those are well documented elsewhere, suffice to say that fsyacc is capable of generating parsers that can handle languages you're probably familiar with.
Recall from last time that lexers take a stream of characters and produce tokens. The do this by matching a regular expression against the input to identify each character. If we assume we have some tokens defined for the elements of our language like PRINT, INT, SEMI (for a ; to separate statements in a statement list), PLUS, MINUS, LPAREN, and RPAREN, we can easily define the regular expressions that produce these tokens from the input.
Adding an .fsl file to the project allows us to define the lexer rules. When the project is built, fslex will run against our file and produce a generated F# file that contains our lexer. Here's what the definition looks like:
{
open System
open Parser
open Lexing
}
let num = ['0'-'9']+
let integer = '-'? num
let whitespace = ' ' | '\t'
let newline = '\n' | '\r' '\n'
rule token = parse
| whitespace { token lexbuf }
| newline { (lexbuf: lexbuf).EndPos <- lexbuf.EndPos.NextLine; token lexbuf }
| "(" { LPAREN }
| ")" { RPAREN }
| "+" { PLUS }
| "-" { MINUS }
| ";" { SEMI }
| integer { INT (Int32.Parse(lexeme lexbuf)) }
| eof { EOF }
| "print" { PRINT }
The initial { } contains F# code that is directly inserted into our generated file. The tokens themselves (anything in all caps) are defined in the parser which we'll see in a minute so we have to "open Parser" to be able to see them. Next we set up some basic patterns including "num" for strings of digits.
Then, we define the token production rules. The left side (immediately following "|") defines the pattern we are matching, while the braces contain the action to execute (and token to return) should the pattern be matched. Note that "whitespace" results in simply calling our "token" function again with the remaining input, effectively ignoring the whitespace. Also, "newline" updates the current line number so should there be a problem the error can correctly report the line it was on. The only other point of interest is that the INT token carries along a piece of integer data (the actual number that was typed).
Armed with our lexer, we can now create an fsy file and build our parser. It looks like this:
%{
open Ast
%}
%start start
%token <int> INT
%token PLUS MINUS LPAREN RPAREN
%token PRINT SEMI EOF
%left PLUS MINUS
%type <stmt> start
%%
start: StmtList EOF { Seq(List.rev $1) }
Expr:
| INT { Int $1 }
| Expr PLUS Expr { BinOp (Plus, $1, $3) }
| Expr MINUS Expr { BinOp (Minus, $1, $3) }
| LPAREN Expr RPAREN { $2 }
Stmt:
| PRINT Expr { Print $2 }
StmtList:
| Stmt { [$1] }
| StmtList SEMI Stmt { $3 :: $1 }
Like the lexer, the parser starts with a code block that simply opens the Ast module with the Ast types defined in it. "%start" indicates the name given to the generated parsing function, while "%type" later on indicates that the function will return a "stmt". Next we have a list of tokens (note that INT is defined to carry a piece of data of type int) and an indication that PLUS and MINUS are left associative. This also defines precedence so we can do things like correct multiplication and division later. Finally we have a list of patterns to match. Like the lexer, the left side matches the input (although now we're matching tokens rather than raw characters) and the right side (in the braces) indicates which type defined in Ast should be returned. The "$x" escapes refer to the tokens matched. For example, Expr PLUS Expr results in a BinOp where the left hand side is the value of the first token ($1), i.e., the first "Expr" and the right hand side is the value of the third token ($3), or the second "Expr". The PLUS token itself is "$2". The last trick is that we end up building the StmtList backwards, for efficiency sake (prepending an element to a list is O(1) while adding to the end is O(n)), so in the "start:" pattern we have to reverse $1 before returning the Seq.
Now we can use our parser with something like this:
let parseText text =
let lexbuf = Lexing.from_string text
Parser.start Lexer.token lexbuf
Calling "parseText" with a valid program ("print (1 + 1)") will result in an instance of "stmt" that we can pass to the evaluator we build in the last article.
Now we have a pretty stable base to work from. Next time we'll add variables and functions and then after that we'll add types other than "int" so we can start to worry about type checking.
Thursday, March 26, 2009
The C# coalesce operator short circuits
Wednesday, March 25, 2009
F# Steals Show Smart Tag Keyboard Shortcut
To rebind it, find View.ShowSmartTag in the keyboard options and set it back to Ctrl-.
Edit: It turns out this is mentioned in the release notes that I neglected to read. Oops.
Monday, March 23, 2009
Writing a Compiler with F# Part 3
Now that we can read user input and pipe it into our evaluator, we need to start implementing the main parts of the compiler. First it's helpful to understand what compilers actually do. In a rough sense, they take the text files containing the code and output an exe or a dll or something, i.e., they transform human readable text into machine code. This is a simplified definition, but it will suffice for our purposes.
It may be tempting to go directly from text into code, but for anything beyond the simplest of languages this ends up being very difficult both to write and maintain. Most compilers divide up the work into several stages that form a pipeline of sorts. Some common stages are:
- Lexing
- The raw sequence of characters is transformed into a sequence of Tokens. For example, the Lexer would consume 'w' 'h' 'i' 'l' 'e' from the input file and return the WHILE token
- Parsing
- The tokens from the Lexer are consumed to produce an Abstract Syntax Tree. An AST is a convenient in-memory representation of the program. More on these in a moment. For example, the Parser might consume VAR IDENTIFIER('i') COLON TYPENAME('int') and produce an instance of our VariableDeclaration class with the Name property set to 'i' and the type set to 'int'
- Type Checking
- Once we have the AST, we can make several passes over it to check the semantics of the language, including that programs are well typed. For example, when looking at an IfStatement we'd want to make sure that the Expression for the if clause was of type bool.
- Other backend phases
- We'll talk more about backend phases like instruction selection, register allocation, and optimizations if we ever get to building the backend. Ultimately these phases involve walking over the AST and finally spitting out machine code (assembly language, IL for .NET, etc.)
What you should see here is that the actual textual representation of the language plays a very small part in this whole process. A large portion of the compiler depends solely on the AST. Only the Lexer and Parser really care whether you end statements with semicolons or have syntactically significant whitespace, for example. Because of this, it's useful to start thinking about the AST first, and then worry about Lexing and Parsing.
In F#, the most common way to model ASTs is through the use of discriminated unions. These are roughly the functional programming equivalent of a polymorphic class hierarchy, although much simplified. Let's look at an AST for a very simple language that lets you print arithmetic expressions (provided you only want to use parentheses and addition/subtraction).
type binop =
| Plus
| Minus
type expr =
| Int of int
| BinOp of binop * expr * expr
type stmt =
| Print of expr
| Seq of stmt list
The keyword 'type' introduces the declaration of a discriminated union. Each option is followed by a |. binop, for example, resembles an Enum that can either be Plus or Minus. The main difference between these unions and enums becomes apparent when you look at 'expr': each of the options can carry data. We can have an expr Int that contains an integer value, or a BinOp that contains a binop (remember Plus or Minus) and two other expressions. We would represent "print 5 + 3" in our AST as Print(BinOp(Plus, Int(5), Int(3)))
Discriminated unions really become powerful when combined with pattern matching. Given the AST above we can easily build a simple evaluator. Here's all we need:
let rec evalE (env,fenv) = function
| Int i -> i
| BinOp(Plus, l, r) -> (evalE (env,fenv) l) + (evalE (env,fenv) r)
| BinOp(Minus, l, r) -> (evalE (env,fenv) l) - (evalE (env,fenv) r)
and eval (env,fenv) = function
| Seq stmts -> List.fold_left eval (env,fenv) stmts
| Print e -> printfn "%d" (evalE (env,fenv) e); (env,fenv)
Ok what's going on here? We've defined two mutually recursive functions, 'eval' for evaluating statements, and 'evalE' for evaluating expressions. We can safely ignore (env,fenv) for now; those will be useful when we add variables and functions. The body of 'eval' says: If I'm handed a Seq of statements, fold the eval function over each statement. Since we don't have variables yet this is could easily just be 'for each statement, evaluate it'. It also says: If I'm handed a Print of some expression, evaluate the expression and then print it out. Evaluating expressions works similarly. If I'm handed a BinOp(Plus) of two expressions, evaluate each one and then add them together.
In these relatively few lines of code, we've built a simple arithmetic evaluator. If you type this stuff into fsi, you can call the evaluator by doing something like:
eval (0,0) (Print(BinOp(Plus,Int(5),Int(6))))
Which will evaluate 5 + 6 and print out 11. Next time we see how to build a simple Lexer and Parser for the language so we don't have to type the AST out manually any more.
Friday, March 20, 2009
Using a custom base class for a generated ObjectContext
Not only does the Entity Framework designer not have first class support for this, it appears that the Entity Framework tool chain itself has no support for this at all. I hope I'm wrong about this, but thus far I've been completely unable to find a way to specify that I want my generated ObjectContext to inherit from my BaseObjectContext instead of just ObjectContext.
Not impressed.
Sunday, March 15, 2009
Writing a Compiler with F# Part 2
Since the ideas I want to mess with are more related to type systems than, say, instruction selection or optimizing passes, I'm going to completely neglect the backend of the compiler for awhile. Initially I'm not going to compile the language at all. Instead I'll just build a simple interpreter to evaluate the type-checked parse tree.
The easiest way to play with this is to make a basic REPL (Read Evaluate Print Loop). Basically a prompt that you can type language snippets into and have them run and the results printed. For F#, the REPL is called fsi.exe. Other languages have this feature as well (in Ruby it's irb.exe).
To get started, I'm going to forget about all the lexing and parsing stuff and get my feet wet with F# by building the framework for a simple REPL.
First, I'll need to print a prompt and get some input. Here's an F# function to handle that:
let getInput (prompt:string) =
(Console.Write(prompt); Console.ReadLine())
Pretty basic stuff. I had to specify the type for "prompt" since Console.Write is overloaded.
Next, I want a basic loop to get input and evaluate it. Functional programming and F# in particular work naturally with sequences as a first class element. To that end, I'm going to model the user input as a sequence of lines. The F# Seq type has a generate method for this purpose. It takes 3 functions: an initializer that returns any data you might need, a generator that given the initial data produces either another element or None to signify the sequence has ended, and a cleanup function. Initially, I don't need any supporting data so both the initialize and cleanup functions can do nothing. Here's what it looks like:
let input = Seq.generate
(fun () -> ()) // init
(fun () ->
match getInput(">") with
| "#quit" -> None
| inp -> Some(inp))
(fun () -> ()) // cleanup
The middle function uses getInput that was defined above and asks the user for input. If they type "#quit" then the sequence ends, otherwise the input is returned.
Now we'll take this sequence and do something with it. Ultimately we'll want to evaluate the input and then keep prompting. Since the statement run might result in new variables being declared or existing ones modified, we'll need some way to remember what happened. The state of our world is referred to as an environment, so we'll write a dummy eval function that takes an environment, evaluates input, and returns the new environment to pass along to the next statement. For now let's use this:
let eval (env:int) (x:string) =
(Console.WriteLine("Evaluating: {0}", x);env)
We ignore the environment, just print out the input, and return the environment unchanged.
The last step is to apply this eval function to our sequence of user input, passing the modified environment forward to the next element. This is a classic case of a fold. We start with an initial environment, call eval on the first item in the sequence, and then pass the resulting environment in when calling eval on the second item. Then the environment returned by eval'ing the second item gets passed into the third, etc. Here's what this looks like:
Seq.fold eval 0 input |> ignore
That's it. We don't care about the final value of the environment so we just pipe it to ignore. With only a few lines of F# we have a basic REPL going and we're ready to start with the real language work next time.
Saturday, March 14, 2009
Writing a Compiler with F#
I've been dabbling with F# off and on since it was first publicly available, but I've never put enough time into it for it to feel natural to me. The language itself has also evolved considerably since the early days.
To take my knowledge of the F# from its current state (simple snippets typed into FSI used to befuddle and amaze people who have never seen a functional language with strong type inference before) into a solid working understanding I'm going to write a compiler for a new programming language. Languages like F# excel at solving problems like this, so this should give me a good exposure to what it's really like.
I also have some ideas regarding programming languages that I want to try out, but I'll talk more about those as they arise. I'm going to start pretty simply for the target language and as time goes by I'll hopefully transition from worrying about the low level stuff like F# syntax into the really interesting stuff like the type system for my language and how it interoperates with the CLR.
My intent is to make a series of posts highlighting the process I'm going through including interesting things about F#, compilers and compiling, and type systems. I'm not getting any Big Ideas about the resulting language - my formal PL background is limited to a solid CS education, reading Pierce's Types and Programming Languages, and lurking Lambda The Ultimate. That is to say, I'm expecting to do things...less than optimally.
Now since I've posted this introduction I actually have to work on this thing. Next time I'll talk about some basics of F# and also compilers.
Wednesday, February 11, 2009
Type.IsAssignableFrom seems backwards
This has come up recently when writing Windsor Interceptors and also methods that use reflection to walk my assemblies and automatically register components with my container. In these scenarios I end up with the concrete type in a variable of type Type, while the interface or base class I'm checking for is statically known. In the midst of my "where" clauses like "where type.IsGenericType && type.IsPublic" it's tempting to write "type.IsAssignableFrom(typeof(IMyInterface))", but this is, of course, incorrect. You have to reverse the order to get "typeof(IMyInterface).IsAssignableFrom(type)". There's a small amount of cognitive dissonance for me every time I have to do it.
What I'm really thinking is "make sure 'type' is an 'IMyInterface'. Why not make it so the API reflects that? Here's a little extension method that will let you write "where type.IsA<IMyInterface>()" instead. This reads a lot more naturally to me.
public static class TypeExtensions
{
public static bool IsA<T>(this Type type)
{
return typeof(T).IsAssignableFrom(type);
}
}
Extension Methods and CodeDom
All you have to do is emit a System.Runtime.CompilerServices.ExtensionAttribute on your static method and the class that contains it. Then just construct the method like a regular static method where the first parameter is the type you want to add the extension to. For example, to emit something like:
public static class StringExtensions {
public static string SayHi(this string instance)
{ ... }
}
you can emit:
[Extension]
public static class StringExtensions {
[Extension]
public static string SayHi(string instance)
{ ... }
}
Then make sure you reference System.Core.dll in your compiler options and everything will work fine.
Friday, November 28, 2008
Using the Windsor Fluent Interface and an XML Configuration file
Boilerplate anything bothers me and boilerplate XML even more so. I wanted a nice programmatic way for the users to say "configure the framework" in their application as a substitute for all the XML. What this meant, however, was that I now needed to configure the container 2 ways: programmatically using the fluent interface available in the trunk, and using a config file.
My first attempt went something like this:
WindsorContainer c = new WindsorContainer("dependencies.config");
c.Register(Component.For<IFrameworkThing>().ImplementedBy<FrameworkThing>();
c.AddFacility<RequiredFacility>();
While that looks ok, the order things happened bit me. Our facility (RequiredFacility in this example) happens to listen to the ComponentModelCreated event raised by the Kernel when a component is added to add a ComponentActivator (more specifics here). Since the XML gets processed (and all the components in it get added) before our facility is added, we miss the events we need to handle.
I needed a way to have my facility in place before adding in the stuff in the config. Due to a lack of documentation and the castle forums guys taking Thanksgiving off, I went down a bunch of fruitless avenues. I looked into loading the framework stuff into a parent container and then creating a child container with
WindsorContainer child =
new WindsorContainer(
parentContainerAlreadyConfigured,
"dependencies.config");
but the parent doesn't get the ComponentModelCreated events from the child.
Eventually I ended up with the following solution. This came from using Reflector (the best documentation for Castle I've found to date) and mimicking what the WindsorContainer constructor itself does.
WindsorContainer container = new WindsorContainer();
container.AddFacility<RequiredFacility>();
//other programmatic config
XmlInterpreter configInterpreter =
new XmlInterpreter("dependencies.config");
configInterpreter.ProcessResource(
configInterpreter.Source,
container.Kernel.ConfigurationStore);
container.Installer.SetUp(
container,
container.Kernel.ConfigurationStore);
The API seems a bit ugly, but it works. I get all the events I need and the users of the framework don't have to deal with any more boilerplate Windsor configuration.
Update: It turns out you can replace all the XmlInterpreter stuff with this:
container.Install(
Configuration.FromXmlFile("dependencies.config"));
This does the same stuff, only it looks a lot nicer.
Friday, October 31, 2008
ASP.NET MVC and form editing scenarios
For example, the user browsers to Customers/Edit?id=1 and gets the Edit view. When submitting the form, the form posts to Customers/Update, which redirects back to Customers/List on success.
ScottGu's blog (and others') have examples for this, but most rely on a simple set of data used for the edit screen. ScottGu's example approach involves catching any exceptions during update and then re-rendering the Edit view. There are a few problems with this approach. The first is that the Url now shows Customers/Update and not Customers/Edit (so the same screen has different Urls). The second issue arises when your Edit view needs more than ViewData.Model to display. Suppose the Customer object has a Status property that you want to pick from a dropdown. To make this work, the Edit action would set ViewData["Statuses"] to the list of allowable statuses. Now, in order for Update to render the Edit view, we'd have to also load up Statuses. Now we're loading Statuses into ViewData in two places, the Edit action and the Update action.
Because of these issues, we've taken a different approach. Inside our base controller we override OnActionExecuted and look for exceptions. If an exception happened, we capture the ModelState and store it in TempData. We then redirect back to where we came from. If no exception happened and our TempData has ModelState stored in it from an invalid form attempt, we restore it.
Conceptually it's pretty simple, and it mostly works with the current beta release. It solves the two issues we had in that the Edit action is the only place the data for the Edit view is populated and since we redirect the Url is always correct.
There are still a few minor issues. One is a bug I found in DropDownList where it doesn't look at the Model to find the selected value. It is documented on CodePlex here..
I've posted a sample solution that uses this technique here. It's just the default MVC app with a new tab added to the page.
Our real application does a lot more than this, including hiding all the unit of work logic and automatically committing if there were no errors, as well as integrating a validation framework based on Castle.Components.Validator and jQuery. The extensibility of the MVC made adding all this stuff pretty easy and clean.
Saturday, September 13, 2008
C# mod operator (%) and negative numbers
A more comprehensive list can be found at Wikipedia.
This came up while trying to learn some WPF. I have a main window and a bunch of child windows that I want to cycle through with ctrl-tab. When I went to add cycling backwards with ctrl-shift-tab I was rewarded with a nice ArgumentOutOfRangeException.
Tuesday, July 01, 2008
NUnit within Visual Studio
It was a bit flaky at first, but a recent release has fixed all the non-trivial problems.
Check it out here.
Tuesday, June 10, 2008
Windsor and Linq DataContexts
<properties>
<connectionString>
Data Source=server;
Initial Catalog=Sample;
Integrated Security=True
</connectionString>
</properties>
...
<component
id="datacontext"
service="Sample.SampleDataContext, Sample"
type="Sample.SampleDataContext, Sample"
lifestyle="transient">
<parameters>
<connection>#{connectionString}</connection>
</parameters>
</component>
Easy, right? Unfortunately if you try to run this and do container.Resolve<SampleDataContext>(); you'll get an error like: "Key invalid for parameter connection." It turns out that what is happening is that Windsor doesn't know which Constructor to use. The generated DataContext has 2 single parameter constructors, one that takes a string named "connection", and the other that takes an IDbConnection named "connection". I think what happens is that the container tries to convert the property to an IDbConnection and it fails.
What we need to do is change the way the constructor is chosen. One simple way is just to add another constructor to your DataContext with a dummy ignored parameter. Like this:
public SampleDataContext(string connection, int ignoreThis)
If you then add <ignoreThis>5</ignoreThis> to the parameters section in the config then Windsor will find your new constructor and everything will work. This, however, is ugly.
A better way is to create a Facility. What we're going to do is assume that all our DataContexts will follow the same pattern, i.e., that we always want to use the constructor that takes a single string parameter.
First, we create a facility that inherits from Castle.MicroKernel.Facilities.AbstractFacility. We want to replace the default ComponentActivator, so we'll need to get ahold of the ComponentModel when it's created. We can override Init like this:
protected override void Init()
{
Kernel.ComponentModelCreated +=
(model) =>
{
if (typeof(System.Data.Linq.DataContext)
.IsAssignableFrom(model.Implementation))
{
model.CustomComponentActivator = typeof(CustomActivator);
}
};
}
Notice we're only setting a custom activator for classes that inherit from DataContext. Now all that's left is to implement CustomActivator. Luckily, the default activator is designed to be inherited from; everything we need to change is virtual. Create CustomActivator that inherits from Castle.MicroKernel.ComponentActivator.DefaultComponentActivator. You'll need a constructor that takes the same parameters. All we need to do is override SelectEligibleConstructor to force the container to choose the single string parameter one. We can do that just like this:
protected override
ConstructorCandidate SelectEligibleConstructor
(CreationContext context)
{
return
Model.Constructors.Cast<ConstructorCandidate>()
.First(c => c.Constructor.GetParameters().Length == 1
&& c.Constructor.GetParameters()[0]
.ParameterType == typeof(string));
}
The final step is just to add the facility to our configuration.
<facilities>
<facility id="linqFacility" type="Core.LinqFacility, Core" />
</facilities>
Now everything works as expected for all DataContexts in our config.
Wednesday, May 14, 2008
Anonymous Interface Implementation
I submitted a Connect item about this (here), but as you can see it won't be making it into this release.
To tide myself over I wrote a version that is built on anonymous types, Reflection.Emit, and Funcs. You can download it here. This is a proof of concept...no warranties...don't use in production...blah blah blah.
As a sample, here's how to create an instance of IEqualityComparer that thinks strings are equal if they are the same length:
Make.Instance<IEqualityComparer<string>>(
new {
Equals = Make.Func(
(string x, string y) => x.Length == y.Length)
})
I had to use Eric Lippert's trick to get lambdas and inferencing working in anonymous types.
Friday, April 04, 2008
DataContractSerializer and 0 length array
I cut my service method down to nearly as simple as it could go:
return new MyClass { Name = "BLARG", Children = new MyClass[0] }
and that was still dying. But when I changed it to
Children = null
everything magically started working.
This really merits more investigation but it's after 5 on a Friday and I'm going home.
Tuesday, March 25, 2008
New stuff
The new laptop is a Lenovo T61p with the 15" screen. I'm running Vista x64 on it and that part has gone smoothly so far. Design-wise, I think I liked my Dell D820 better. The T61p feels much heavier than the Dell (though I do have a 9 cell battery in this one), the screen is slightly off center, and I don't like the keyboard layout at all. I'm perhaps overly concerned about keyboard layouts and this one just doesn't do it for me. The biggest issues for me are that the arrow keys aren't normal sized keys, the escape key sits above F1, and the lower left corner is a special Fn key, rather than Ctrl. By default, Fn-Space triggers the built in Lenovo Zoom utility, which is really jarring when you just intended to pop up intellisense. I'm sure I'll get used to all that though.
The new laptop bag is an Ogio Metroid and it's nothing but fantastic. I was originally worried that the T61p wouldn't fit, but it easily does. The Metroid is a backpack with a laptop pocket, but it also has a file section in the front that keeps my papers from sliding down and getting crumpled in the main pocket. There's plenty of room for all my junk and the mp3 player pocket fits my external hard drive just fine. Plus, I got it from amazon for $60 (of which work reimbursed me $40).