V.B.
V.B.

Reputation: 6382

Using F# quotations to detect code changes

I need to cache results from heavy calculations done by several different classes inheriting from the same base class. I was doing run-time caching by subclass name. Now I need to store the results on disk/DB to avoid long recalculations when I restart my app, but I need to invalidate cache if I change the code inside Calculate().

type BaseCalculator() =
    let output = ConcurrentDictionary<string, Series<DateTime, float>>() // has public getter, the output is cached by the caller of Calculate() method

    abstract Calculate: unit->unit

type FirstCalculator() =
    inherit BaseCalculator()
    override this.Calculate() = ... do heavy work here ...

From this question and answers I have learned that I could use [<ReflectedDefinition>] on my calculate method. But I have never worked with quotations myself before.

The questions are:

Upvotes: 0

Views: 144

Answers (2)

V.B.
V.B.

Reputation: 6382

I have found that Mono.Cecil is surprisingly easy to use, and with it I could hash all member bodies of a type, including base type.

This SO question was very helpful as a starting point.

Upvotes: 0

Tomas Petricek
Tomas Petricek

Reputation: 243071

Could I use a hash code of quotations to uniquely identify the body of the method, or there are some guids or timestamps inside quotations?

I think this would work. Have a look at FsPickler (which is used by MBrace to serialize quotations). I think it can give you a hash of a quotation too. But keep in mind that other parts of your code might change (e.g. another method in another type).

Could ReflectedDefinition be applied to the abstract method and will it work if I override the method in C#, but call the method from F# runner?

No, the attribute only works on F# methods compiled using the F# compiler.

Is there other simple and reliable method to detect code changes in an assembly automatically, without quotations?

I'm not sure. You could use GetMethodBody method and .NET reflection to get the IL, but this only gives you the immediate body - not including e.g. lambda functions, so changes that happen elsewhere will not be easy to detect.

A completely different approach that might work better would be to keep the calculations in FSX files in plain text and compile them on the fly using F# Compiler Service. Then you could just hash the source of the individual FSX files (on a per-computation basis).

Upvotes: 3

Related Questions