Saturday, August 14, 2010

Batch to Powershell: Title

If you try to set the title of the window in powershell, 'title' won't work; but you can set the title using the $host object
 PS C:\> $Host.UI.RawUI.WindowTitle = "Donkey" 


You can also mess with other fun things like colors eg:

PS C:\>  $Host.UI.RawUI.BackgroundColor = [ConsoleColor]::Red 


If you're a big title user and have title burned into your muscle memory you can always create function called title e.g.:

 PS C:\Temp> function title ($t) {$host.UI.RawUI.WindowTitle=$t }
PS C:\Temp> title Donkey2


Have fun moving into powershell.

Wednesday, August 4, 2010

Powershell: Returning ScriptBlocks and Closures

Powershell lets you return scriptblocks (aka anonymous functions) from functions, for example:
function generateAdder ($n)
{
{
param ($x)
$n+$x
}
}


 
PS C:\> $add4 = generateAdder 4
PS C:\> & $add4 7
7

If you've used languages with closures you'd have expected to get back a function that adds 4 to a passed in value. You'd expect that because $n=4 was in lexical scope when we created the scriptblock to be returned. Recall powershell is dynamically scoped so we don't need to bind ($n) to a lexcial location, instead we can pick up $n from our current environment:

PS C:\> $n = "Hello"
PS C:\> & $add4 7
Hello7

What if you want to instantiate a closure with powershell instead? Luckily someone thought of that and you can do:

function generateAdder2 ($n)
{
{
param ($x)
$n+$x
}.GetNewClosure()
}


PS C:\> $add4 = generateAdder2 4
PS C:\> & $add4 7
11


Leave a comment if you use these features, I’m curious what you’d use them for.

Sunday, August 1, 2010

Batch to Powershell: dir /s

I often go looking for a file in batch, aka

c:\Program Files (x86)>dir /s fsi*
Volume in drive C has no label.
Volume Serial Number is 8EDE-D64E

Directory of c:\Program Files (x86)\Microsoft F#\v4.0

03/19/2010 02:02 PM 230,216 Fsi.exe
09/30/2009 08:08 PM 158 Fsi.exe.config
2 File(s) 230,374 bytes

Unfortunately this doesn't 'just work' in powershell. A quick search on the internet shows in powershell 'dir /s' becomes 'dir -r', but the following doesn't work either:

PS C:\Program Files (x86)> dir -r fsi*
PS C:\Program Files (x86)>

What's going on? Let's check the help:

PS C:\Program Files (x86)> help dir

NAME
Get-ChildItem

SYNOPSIS
Gets the items and child items in one or more specified locations.


SYNTAX
Get-ChildItem [[-Path] ] [[-Filter] ] [-Exclude ] [-For
ce] [-Include ] [-Name] [-Recurse] [-UseTransaction] []

Get-ChildItem [-LiteralPath] [[-Filter] ] [-Exclude ]
[-Force] [-Include ] [-Name] [-Recurse] [-UseTransaction] []


Ahh, path and filter are two separate arguments in powershell. This means we get 2 choices.



A) Pass a path to the dir command (pass ‘.’ for current directory):



PS C:\Program Files (x86)> dir . fsi* -r

Directory: C:\Program Files (x86)\Microsoft F#\v4.0


Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 3/19/2010 2:02 PM 230216 Fsi.exe
-a--- 9/30/2009 8:08 PM 158 Fsi.exe.config
PS C:\Program Files (x86)>

B) Explicitly pass the -filter argument name (which we can abbreviate to -fi)

PS C:\Program Files (x86)> dir -r -fi fsi*


Directory: C:\Program Files (x86)\Microsoft F#\v4.0


Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 3/19/2010 2:02 PM 230216 Fsi.exe
-a--- 9/30/2009 8:08 PM 158 Fsi.exe.config
PS C:\Program Files (x86)>


OK you’re thinking who cares, I can still do dir /s faster in batch? Ah, but you can’t do this:



 PS C:\Program Files (x86)> dir -r -fi fsi* | Where-Object {$_.Length -gt 200KB}


Directory: C:\Program Files (x86)\Microsoft F#\v4.0


Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 3/19/2010 2:02 PM 230216 Fsi.exe
PS C:\Program Files (x86)>


Have fun, and remember read the docs when things don’t work as you’d expecxt:)

Saturday, July 17, 2010

F# Tricks: Concise BoolToInt

As a C# programmer, you'd probably write BoolToInt as follows in F#:
	let boolToInt3 b = 
if b = true then
1
elif b = false
0


Not a big win over C# yet, but a few things to point out about the concise syntax: Indentation implies blocks. There is no 'return' keyword. This function is statically typed, you don't see types since the compiler infers the types.



As a novice F# programmer a trick you learn is pattern matching. Pattern matching is like a case statement, but it's an expression and it's really powerful. I'll go into more details on pattern matching in future posts. For now, notice the elegance of the below:



	let boolToInt2 b = 
match b with
| true -> 1
| false -> 0

Pattern matching is so useful to F# there is a syntax for creating a function of one parameter that only pattern matches, using that syntax, we define boolToInt in the final form of:

	let boolToInt3 = function 
| true -> 1
| false -> 0

Thursday, June 10, 2010

F# Tricks: Collecting Some Optional Values

Skip this post if you have no idea what F# is, and think LINQ is stupid.

When you map inputs to outputs with a function that can return None, or Some Output, you get an annoying issue of having a list containing Nones, and Somes. For example:

// Contains both encrypted and un-encrypted files: 
let listOfFiles:Seq

// Return a decrypted File, or None if the file can't be decrypted.
let decryptFile file
match file with
| isFileDecryptable file -> Some DecryptFile file
| _ -> None

// decryptedFiles contains Nones, intertwined with some Some DecryptedFiles
let decryptedFiles = listOfFiles |> Seq.map decryptFile
Here are two ways to remedy that:

// To get a list of only decrypted files you could do:
let realDecryptedFiles = decryptedFiles |> Seq.filter Option.isSome |> Seq.map Option.get

// However, I prefer the more concise version of:
let realDecryptedFiles = decryptedFiles |> Seq.collect Option.toList
If you're an F# guru I'd love to hear your thoughts on this.

Friday, May 21, 2010

The power of shift clicking – Copy As Path

 

copyaspath

Have you ever been in explorer and needed to get the path of a file?

Turns out that feature is built into Windows 7! If you shift right click on a file, the menu contains a copy as path link.  Sweet!

Saturday, May 15, 2010

Making the FSharp interpreter (fsi) run in 64bit!

I love F#!  It’s all the power of functional programming with the training wheels of c# when you need it. All the prototype/REPL power of powershell and python, with the built in test cases I like to call static typing. All the power of static typing, with out the hassle of specifying types every where thanks to implicit typing.

But, there is one annoying problem, I crunch very large data sets and fsi.exe runs as a 32 bit application. This means when I load my data sets and iterate through them FSI takes up 1.6 GB of RAM (maximum for a 32bit app), and spends 100% of its time in GC.

An aside for you who are thinking: 1.6GB is enough RAM!? – Igor must be a really crappy programmer!!! 1.6GB could be plenty, but why should I spend time adding complexity to my code when I have a superb memory manager, a 64 bit address space and a 3 year old dev machine that has 16GB of RAM, and 8 processors?  Today, I get no value from optimizing my data set for memory utilization -- I’m better off making my data cruncher a 64 bit application.

Back to work.  First, lets open up the Visual Studio command prompt (it has the tools we need in its path) and find fsi.exe.

C:\Program Files (x86)\Microsoft F#\v4.0>dir fsi.*
Volume in drive C has no label.
Volume Serial Number is 8EDE-D64E

Directory of C:\Program Files (x86)\Microsoft F#\v4.0

03/19/2010 02:02 PM 230,216 Fsi.exe
09/30/2009 08:08 PM 158 Fsi.exe.config
2 File(s) 230,374 bytes

Lets make sure it's 32 bit - we do that with a tool called corflags.

C:\Program Files (x86)\Microsoft F#\v4.0>corflags fsi.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.

Version : v4.0.30319
CLR Header: 2.5
PE : PE32
CorFlags : 11
ILONLY : 1
32BIT : 1
Signed : 1

Next we use corflags to make fsi 64bit. This will unsign the fsi.exe but this hasn't affected anything for me yet.

 

C:\Program Files (x86)\Microsoft F#\v4.0>corflags /32bit- /force fsi.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.

corflags : warning CF011 : The specified file is strong name signed. Using /For
ce will invalidate the signature of this image and will require the assembly to
be resigned.

Lets double check it worked:

 
C:\Program Files (x86)\Microsoft F#\v4.0>corflags fsi.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.

Version : v4.0.30319
CLR Header: 2.5
PE : PE32
CorFlags : 9
ILONLY : 1
32BIT : 0
Signed : 1

Finally fire up F#, and it's now in 64 bit - yippee!