Reputation: 9397
Given the following two approaches, what would the cons and pros of both, when it comes to function composition?
Approach 1
let isNameTaken source name =
source |> Query.Exists(fun z -> z.Name = name)
let usage : Customer = isNameTaken source "Test"
Approach 2
let isNameTaken f name =
f(fun z -> z.Name = name)
let usage : Customer = isNameTaken (source |> Query.Exists) "Test"
Is it just silly to pass (source |> Query.Exists)
in Approach 2 - is it too extreme?
Upvotes: 1
Views: 130
Reputation: 49209
I think the answer to your question has to do with two main criteria. Which is more important, the readability of the code or the decoupling of the query from isNameTaken
. In this particular case, I'm not sure that you get much at all from decoupling the query and it also seems like your decoupling is partial.
The thing I don't like about this is that in both cases, you've got z.Name
tightly coupled into isNameTaken
, which means that isNameTaken
needs to know about the type of z
. If that's OK with you then fine.
Upvotes: 0
Reputation: 243096
It depends on the wider context. I would generally prefer the first approach, unless you have some really good reason for using the second style (e.g. there is a number of functions similar to Query.Exists
that you need to apply in a similar style).
Aside - I think your second example has a couple of issues (e.g. the piping in source |> Query.Exists
would have to be replaced with (fun pred -> source |> Query.Exists pred)
which makes it uglier.
Even then, the second approach does not really give you much benefit - your isNameTaken
is simply a function that tests whether a customer name equals a given name and then it passes that as an argument to some f
- you could just define a function that tests name equality and write something like this:
let nameEquals name (customer:Customer) =
customer.Name = name
let usage = source |> Query.Exists (nameEquals "Test")
More generally, I think it is always preferable to write code so that the caller can compose the pieces that are available to them (like Query.Exists
, nameEquals
etc.) rather than In a way that requires the caller to fill some holes of a particular required shape (e.g. implement a function with specified signature).
Upvotes: 3