You can also place blocks of code in a list and recurse through the list until the user is found.
let cacheUser user =
cache.set(user.id,user)
user
let anonymousUser id =
Some(new User())
let sourceList = [(fun id -> cache.getUser(id),
(fun id -> db.getUser(id)),
anonymousUser]
let getCachedUser id =
sourceList
|> List.pick (fun source -> source id)
|> cacheUser
That's one of the main things I like about functional programming: a lot of logicy code smells can be factored away into reusable generic functions like, in this case, List.pick.
Likewise, engineers who have at least played with FP tend to be sensitive to code smell. In the absence of other, firmer data, I'm willing to loan some trust to a programmer with FP experience.
I've done this sort of thing to satisfy DRY in general (this kind of nesting problem is quite repetitive), and to generally make the intention more obvious. It's not so pretty in certain other languages, but still worth it.
F# always gets me in the editing mode because after I write it the first time I realize there is some built in function that makes the whole thing so much easier. I realized my match statement inside of a recursive function was just reimplementing List.pick