Given an F# record:
type R = { X : string ; Y : string }
and two objects:
let a = { X = null ; Y = "##" }
let b = { X = "##" ; Y = null }
and a predicate on strings:
let (!?) : string -> bool = String.IsNullOrWhiteSpace
and a function:
let (-?>) : string -> string -> string = fun x y -> if !? x then y else x
is there a way to use F# quotations to define:
let (><) : R -> R -> R
with behaviour:
let c = a >< b // = { X = a.X -?> b.X ; Y = a.Y -?> b.Y }
in a way that somehow lets (><)
work for any arbitrary F# record type, not just for R
.
Short: Can quotations be used to generate F# code for a definition of (><)
on the fly given an arbitrary record type and a complement function (-?>)
applicable to its fields?
If quotations cannot be used, what can?
You could use F# quotations to construct a function for every specific record and then compile it using the quotation compiler available in F# PowerPack. However, as mentioned in the comments, it is definitely easier to use F# reflection:
This function takes records, gets their fields dynamically and then applies
f
to the fields. You can use it to imiplement your operator like this (I'm using a function with a readable name instead):The solution using Reflection is quite easy to write, but it might be less efficient. It requires running .NET Reflection each time the function
applyOnFields
is called. You could use quotations to build an AST that represents the function that you could write by hand if you knew the record type. Something like:Generating the function using quotations is more difficult, so I won't post a complete sample, but the following example shows at least a part of it:
Once you build the right quotation, you can compile it using F# PowerPack. See for example this snippet.