Indexer

If your have a type that rep­re­sents a col­lec­tion of val­ues, adding a cus­tom indexer gives you a nat­ural way to index directly into the object using the .[ ] operator.

Take this sim­ple Cal­en­dar class for instance, which keeps a map (F# equiv­a­lent of a Dictionary<TKey, TValue>) of notes against Date­Time values:

image

By adding a cus­tom indexer here I’m now able to write code like this:

image

Also, as you may have noticed already, F# allows you to use non-integer para­me­ters in your indexer! In this case, I’m using a tuple of int * string * int. You can use this indexer from your C# code too:

image

One-Dimensional Slicer

That’s pretty cool, but we can go a step fur­ther by allow­ing you to use slicers on our types too. To allow users to get all the notes asso­ci­ated with a range of years, e.g. from 1999 to 2009, let’s add a slicer:

image

So now we can do this:

image

Two-Dimensional Slicer

Pretty awe­some, right? But what if we want to refine our search cri­te­ria even more and let you spec­ify a year range as well a range of months, e.g. get me all notes for April/May/June in the years 1999 to 2009. Thank­fully, F# lets you define a two-dimensional slicer too:

image

This two-dimensional slicer allows me to query the cal­en­dar with a year range as well as a month range:

image

As you can see, index­ers and slicers give the con­sumers of your code a much more intu­itive way to inter­act with the data encap­su­lated in your type. Keep in mind though, that F# does not allow you to add slicer with more than two dimen­sions, but I think two-dimensional slicers should be good enough for most day-to-day requirements.

Update 2011/11/08:

Swapped out my ver­bose optional argu­ment han­dling with default­Arg as Arseny Kapoulkine pointed out in the comments.

Share

3 Responses to “F# – Adding custom indexer and slicer to your type”

  1. Thanks, this is use­ful.
    Your method of han­dling optional argu­ments is quite ver­bose, default­Arg will do just fine (i.e. let lbYear = default­Arg lower­Bound­Year DateTime.MinValue.Year)

  2. theburningmonk says:

    Arseny — Thanks for the feed­back, default­Arg had com­pletely skipped my mind when I put the exam­ple together!

  3. […] can even add your own multi-dimensional index­ers to sup­port sim­i­lar behav­iours in your type too! Tweet Jan­u­ary 10, 2012 | […]

Leave a Reply