CodeDOM and poor man's lambdas -- Part 2
Unfortunately there is one major sticking point in getting the generation to work for F# -- local variables are declared as let mutable
rather than as a ref
type which means that the necessary closure cannot be made; this is rather stronger than the lack of support for CodeDefaultValueExpression
, which can be fudged around, or for nested types (which just become mutually recursive), though with up-front decision as to the language to generate (rather than making the choice following the expression tree), we could replace problematic elements with snippets.
That aside, the main operation looks like this, similar to the previous examples
If we eschewed F# support entirely, and used a partial class, then we could skip the constructor and field declarations and provide the input by any other mechanism of our choice in a hand-written part.
Generating the closure classes is a simple matter -- especially as the names of the parameters can be used as fields directly without any sigils, provided that they never contain the @this
or proxy
name by convention. This makes the closure class approach slightly simpler than a snippet driven use of direct lambda syntax, where local variable names to hold out parameters would in general have to be generated so as not to clash with any of the arguments:
where the individual field declarations have to work around the decorations for out
or ref
, thus:
The generation of the proxy methods is equally mechanical
So, given a simple type
we generate
The F# code contains
Manually replacing this with
then shows up on the next line
as an error The mutable variable 'proxy' is used in an invalid way. Mutable variables cannot be captured by closures. Consider eliminating this use of mutation or using a heap-allocated mutable reference cell via 'ref' and '!'.
; and as there are no readonly
locals in the CLR -- it's all F# compiler magic that gives the illusion of same -- we're stuck with no control to tweak to make proxy
immutable in the F# output.