There was recently a project I was working on that required a recursive call. The problem was, that the function returned an async workflow, and in my inexperience, I was running into the problem that I didn’t know what each exit point should return exactly. This is a problem, because in F# all code paths must return the same type, and I wasn’t sure when I needed to wait for an async call, or return the async workflow itself. The idea behind the function was that it would query the database for a specific string, and if it didn’t find anything, it would shorten the string and try again, until the string was a certain length. After some looking around online, I came across this FSSnip that describes a recusive async function:
1: 2: 3: 4: 5: 6:
work is the async work that we want to recursively call. We then check if the result was ok using a specific resultOk function, or check if a set number of retries has been reached. If yes, we simply return that result of the async work. Otherwise, we bind the same function, with the same async work to the current async builder and return that.
Once I understood what was going on, I was able to come up with my own solution that worked better for my use case:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
So here’s my version, obviously not perfect, and looking at it now, I already want to make some modifications. But you can see on line 12 where it returns the query result once the string is below a certain threshold, and otherwise it returns a recursive call to itself, which is not an async workflow. However, if at any point it finds something before the threshold, it returns the result wrapped in an async workflow, because the query function itself is also one. That’s the key here.
static val E : float
static val PI : float
static member Abs : value:float -> float + 6 overloads
static member Acos : d:float -> float
static member Acosh : d:float -> float
static member Asin : d:float -> float
static member Asinh : d:float -> float
static member Atan : d:float -> float
static member Atan2 : y:float * x:float -> float
static member Atanh : d:float -> float