A parameterized active pattern to match the first elements of an array

Been writing code in F# for almost a year and never blogged about it. Time to change that ;) Earlier today someone asked the following on twitter:

Is it possible to pattern match the first part of an array in #FSharp? Something like | 1::2::3::tail but for arrays? #lazyweb

I accepted the challenge ;)

Comments are disabled on this blog

As of now comments are disabled on this blog. Want to reply? Write your own post and pingback or engage a conversation on twitter with @timvw.

The curious case of trailing spaces in SQL

A while ago I was quite surprised to see that the following query returns 1 instead of 0:


SELECT COUNT(*) WHERE N'Tim' = N'Tim '; -- notice the trailing space

Apparently this is just standard behaviour. Here is an extract from sql1992.txt (Section 8.2 Paragraph 3):

     3) The comparison of two character strings is determined as fol-
            lows:

            a) If the length in characters of X is not equal to the length
              in characters of Y, then the shorter string is effectively
              replaced, for the purposes of comparison, with a copy of
              itself that has been extended to the length of the longer
              string by concatenation on the right of one or more pad char-
              acters, where the pad character is chosen based on CS. If
              CS has the NO PAD attribute, then the pad character is an
              implementation-dependent character different from any char-
              acter in the character set of X and Y that collates less
              than any string under CS. Otherwise, the pad character is a
              .

            b) The result of the comparison of X and Y is given by the col-
              lating sequence CS.

            c) Depending on the collating sequence, two strings may com-
              pare as equal even if they are of different lengths or con-
              tain different sequences of characters. When the operations
              MAX, MIN, DISTINCT, references to a grouping column, and the
              UNION, EXCEPT, and INTERSECT operators refer to character
              strings, the specific value selected by these operations from
              a set of such equal values is implementation-dependent.

Sample query to demonstrate influence of collation in Sql Server

Lately I had the pleasure to investigate collations and here is a sample query that demonstrates how a collation impacts the behaviour of a query:

WITH [Words] AS (
	SELECT N'Een' AS [word]
	UNION ALL
	SELECT N'Eèn'
	UNION ALL
	SELECT N'EEN'
)
	SELECT [word]
	FROM [Words]
	WHERE [word] 
		--COLLATE Latin1_General_CS_AS -- returns Een
		--COLLATE Latin1_General_CI_AI -- returns Een, Eèn and EEN
		--COLLATE LAtin1_General_CI_AS -- returns Een and EEN
		COLLATE Latin1_General_CS_AI -- returns Een and Eèn
		= N'Een';

Copy all mp3 files in Music folder to USB dribe

Copying all mp3 files from my Music folder to a USB drive is pretty easy on my Macbook:

find Music -name *.mp3 -exec cp {} /Volumes/SANDISK \;

Using eID on OS X Mountain Lion

Last week or so I got myself a MacBook Air and I am really loving it so far. Today I needed to use my eID so I installed the middleware application without any hassle but had a hard time configuring Safari. Apparently Apply removed support for PKCS #11 in OS X Mountain Lion. After installing SmartCard Services the certificates appeared in the Keychain and I became able to authenticate on websites using my certificate

Add missing books to iTunes

These days i read most books on my ipad. The problem is that iTunes does not seem to add pdf files when i choose ‘Add Folder’ to the library. So here is a small application that adds them one by one (way too lazy/unmotivated to do this by hand).

https://gist.github.com/2759128

Multiclean solution

One of my favorite powershell commands when cleaning up:

$RootFolder = 'C:\tfs'
Get-ChildItem $RootFolder bin -Recurse | Remove-Item -Recurse
Get-ChildItem $RootFolder obj -Recurse | Remove-Item -Recurse

An example of Common Table Expression and Window function usage…

Earlier this week some colleague had been assigned a maintenance task and asked me how I would solve it. Every customer is permitted to have an amount of publications. All excess publications should be removed from the system (only the n most recent ones are permitted to remain on the system).

Here is an example of the Customer table:

CREATE TABLE [dbo].[Customer](
	[CustomerId] [int] IDENTITY(1,1) NOT NULL,
	[CustomerName] [nvarchar](50) NOT NULL,
	[PermittedPublications] [int] NOT NULL
);

INSERT INTO [dbo].[Customer] 
			([CustomerName], [PermittedPublications]) 
VALUES	
			('timvw', 2),
			('mike', 3);

An example of the customer publications table:

CREATE TABLE [dbo].[Publication](
	[PublicationId] [int] IDENTITY(1,1) NOT NULL,
	[CustomerId] [int] NOT NULL,
	[PublicationName] [nvarchar](50) NOT NULL,
	[PublicationTime] [datetime2] NOT NULL
);
                         
INSERT INTO [dbo].[Publication] 
			([CustomerId], [PublicationName],[PublicationTime])
VALUES      
			((SELECT [CustomerId] FROM [dbo].[Customer] WHERE [CustomerName] = 'timvw'), 'tim pub1', SYSUTCDATETIME()),
			((SELECT [CustomerId] FROM [dbo].[Customer] WHERE [CustomerName] = 'timvw'), 'tim pub2', SYSUTCDATETIME()),
			((SELECT [CustomerId] FROM [dbo].[Customer] WHERE [CustomerName] = 'timvw'), 'tim pub3', SYSUTCDATETIME()),
			((SELECT [CustomerId] FROM [dbo].[Customer] WHERE [CustomerName] = 'timvw'), 'tim pub4', SYSUTCDATETIME()),
			((SELECT [CustomerId] FROM [dbo].[Customer] WHERE [CustomerName] = 'mike'), 'mike pub1', SYSUTCDATETIME()),
			((SELECT [CustomerId] FROM [dbo].[Customer] WHERE [CustomerName] = 'mike'), 'mike pub2', SYSUTCDATETIME());

My colleague was keen on using some cursor logic, but I demonstrated him how a set-based alternative:

		
WITH [RankedPublication] AS (
	SELECT [CustomerId]
	      ,[PublicationId]
	      ,[PublicationName]
	      ,[PublicationTime]
	      ,ROW_NUMBER() OVER(PARTITION BY [CustomerId] ORDER BY [PublicationTime]) AS [PublicationRank]
	FROM [dbo].[Publication]
), [ExcessPublication] AS (
	SELECT [PublicationId]
	FROM [RankedPublication]
	INNER JOIN [dbo].[Customer] ON [Customer].[CustomerId] = [RankedPublication].[CustomerId]
	WHERE [PublicationRank] > [Customer].[PermittedPublications]
)
	DELETE FROM [dbo].[Publication]
	WHERE [PublicationId] IN (SELECT [PublicationId] FROM [ExcessPublication]);

Say no to primitives in your API.. and make your software more explicit

A while ago I wrote some code like this:

public interface ICanBroadcast
{
 public void Broadcast(string message) { ... }
 public void Broadcast(string message, string author) { ... }
}

A bit later the requirements changed and from now on it was required to specify the topic:

public interface ICanBroadcast
{
 public void Broadcast(string message, string topic) { ... }
 public void Broadcast(string message, string author, string topic) { ... }
}

In case you were using Broadcast(string message) the compiler would rightfully inform you that no such method exists. In case you were using Broadcast(string message, string author) the compiler does not catch the error and incorrectly uses the author as topic. I can only hope that you have a suite of tests that makes you notice that something is wrong when you upgrade to my latest release.

Let’s make the difference between an Author and a Topic more explicit (to our API consumers and the compiler) by creating explicit types to represent the concepts:

public interface ICanBroadcast
{
 public void Broadcast(Message message, Topic topic) { ... }
 public void Broadcast(Message message, Author author, Topic topic) { ... }
}

The joy of using a typed language ;)