Yan Cui
I help clients go faster for less using serverless technologies.
This article is brought to you by
Don’t reinvent the patterns. Catalyst gives you consistent APIs for messaging, data, and workflow with key microservice patterns like circuit-breakers and retries for free.
Indexer
If your have a type that represents a collection of values, adding a custom indexer gives you a natural way to index directly into the object using the .[ ] operator.
Take this simple Calendar class for instance, which keeps a map (F# equivalent of a Dictionary<TKey, TValue>) of notes against DateTime values:
By adding a custom indexer here I’m now able to write code like this:
Also, as you may have noticed already, F# allows you to use non-integer parameters 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:
One-Dimensional Slicer
That’s pretty cool, but we can go a step further by allowing you to use slicers on our types too. To allow users to get all the notes associated with a range of years, e.g. from 1999 to 2009, let’s add a slicer:
So now we can do this:
Two-Dimensional Slicer
Pretty awesome, right? But what if we want to refine our search criteria even more and let you specify 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. Thankfully, F# lets you define a two-dimensional slicer too:
This two-dimensional slicer allows me to query the calendar with a year range as well as a month range:
As you can see, indexers and slicers give the consumers of your code a much more intuitive way to interact with the data encapsulated in your type. Keep in mind though, that F# does not allow you to add slicer with more than two dimensions, but I think two-dimensional slicers should be good enough for most day-to-day requirements.
Update 2011/11/08:
Swapped out my verbose optional argument handling with defaultArg as Arseny Kapoulkine pointed out in the comments.
Whenever you’re ready, here are 3 ways I can help you:
- Production-Ready Serverless: Join 20+ AWS Heroes & Community Builders and 1000+ other students in levelling up your serverless game. This is your one-stop shop for quickly levelling up your serverless skills.
- I help clients launch product ideas, improve their development processes and upskill their teams. If you’d like to work together, then let’s get in touch.
- Join my community on Discord, ask questions, and join the discussion on all things AWS and Serverless.
Thanks, this is useful.
Your method of handling optional arguments is quite verbose, defaultArg will do just fine (i.e. let lbYear = defaultArg lowerBoundYear DateTime.MinValue.Year)
Arseny – Thanks for the feedback, defaultArg had completely skipped my mind when I put the example together!
Pingback: F# equivalent of C#’s Object Initialization syntax | theburningmonk.com
Just what I wanted to know! Thank you :)