A Monad for COM Interop

Well, I finally got to write my first monad. Seems I am getting the hang of it now. Reading about monads only takes you so far. Its not until you do it yourself that you truly grok monads.

In my case I have a monad implementation to manage COM object references. I am pulling data from Excel into F# for an optimization problem. Excel interaction is via COM. COM requires that if you acquire an object reference then you have to eventually release it. My code was getting messy managing COM object references. Now with a monad managing object references the code ends up being a lot cleaner.

The monad implementation uses F# workflows so that you can write code such as:

com {
let aRange = usedRange.Range(sprintf "%d:%d" 1 1) 
return aRange.Value2 : ?> Object[,] } |> Com.Run

Assuming ‘usedRange’ is a reference to Excel’s used range of cells, the above code will return the values of the entire first row as a multi-dimensional array. The let binding in the ‘com’ monad will automatically release the reference to ‘aRange’ COM object when it goes out of scope. Your code does not have to manage that.

When working with COM avoid ‘dots’ in succession as in:

   let range = usedRange .Find(What="xyz") .Offset(1,1)

instead use:

let r1 = usedRange.Find(What="xyz")
let r2 = r1.Offset(1,1)

With dots in succession, implicit COM references are created that cannot be released as there is no handle to address them. Use a let binding for each new COM object referenced so that it gets released by the monad.

You can download the COM monad from the following link:

https://gist.github.com/736343

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s