I have several generic inline functions, e.g.:
let inline getRatesImpl<'T when 'T : (member enantiomer : 'T) and 'T : equality>
(d : Dictionary<'T, (ReactionRate option * ReactionRate option)>)
(calculateRates : 'T -> RelatedReactions<'T>)
(r : 'T) =
match d.TryGetValue r with
| true, rates ->
rates
| false, _ ->
updateRelatedReactions d (calculateRates r) r
The functions are used like that:
type FoodCreationModel (p : FoodCreationParam) =
let rateDictionary = new Dictionary<FoodCreationReaction, (ReactionRate option * ReactionRate option)>()
let calculateRates _ = getRates (Some p.foodCreationRate, Some 1.0) (None, None)
member __.getRates r =
getRatesImpl rateDictionary calculateRates r
member __.inputParams = p
When I put a break inside getRatesImpl
it is not hit in FSI. Even if I put a break, for example, on getRates
(on line getRatesImpl rateDictionary calculateRates r
) and then press F11, then FSI does not get inside inline getRatesImpl
. However, it does work and I can check that by looking at how the dictionary changes before and after the call.
Some of these inline functions are quite complicated and I really need to debug them once in a while.
The question is how?
Your code probably can be changed to avoid the need for complicated inline
s.
One way to avoid using SRTP is passing the required functions as a parameter instead of a constraint:
let getRatesImpl
(d : Dictionary<'T, (ReactionRate option * ReactionRate option)>)
(getEnantiomer: 'T -> 'T)
(calculateRates : 'T -> RelatedReactions<'T>)
(r : 'T) =
match d.TryGetValue r with
| true, rates ->
rates
| false, _ ->
updateRelatedReactions d getEnantiomer (calculateRates r) r
now getRatesImpl
does not need to be inlined.
If more than one function is needed then a record of functions can be passed.