My most recent "Aha!" moment with the language is to finally wrap my head around the standard
Event module -- a sort of lightweight subset of the Reactive Extensions for .net -- while starting to do some more GUI programming in F#, which is making belated use of the GTK#/Glade spikes I made about a year ago.
It may not make much difference in the simplest cases where
naively went to
but which is equivalent to, using the
At this point the main difference is the change in the function signature -- first, it is a real F# function rather than being forced to use the implicit cast from a fun to a delegate, even if the function signatures look compatible on the surface; second the function passed to
Event.add doesn't have the source argument (but, as shown, that can be brought in as a closure).
So that's a small win from the beginning -- but that just scratches the surface. Where it actually shines is where multiple sources of events have to be handled in much the same way. For example, given a menu containing recently accessed files, with selection meaning to re-open that file, as if they had been selected from a file open action
All the inhomogeneity of the event sources (button click, menu item activation) and their associated
EventArgs types is smoothed away by appropriate
Event.map calls and the use of closures; different validations are handled by appropriate
Event.choose invocations; and then the whole ensemble is gathered together by an appropriate fold with
Event.merge as the accumulator.
True, there is nothing here that could not be achieved by making old-style handler functions for
AddHandler from equivalent appropriately composed function chains -- the path I was starting to take for this bit of plumbing before I was indirectly reminded of this feature, and dug up this series of posts from a couple of years back (so slightly dated in the details). The big difference that using the
Event module makes is that it is more expressive of intent, and separates the concerns -- general event handling plumbing vs this application's business logic -- explicitly.