# How to require that a function argument be a pure function or a function-style replacement rule?

I'm trying to write a function whose first argument must be another function, defined either as a pure function or a function-style replacement rule. I don't know how to specify a condition on the argument to achieve that. I know I can use g[func_Function,…] to require pure functions, but functions defined via replacement rules don't have a useful Head.

Here's an example:

f[x_] := x^2 - 1;
g[func_?MatchQ[#, _[___]] &, a_, b_] := func[a + b];
g[f, 1, 2]
(* g[f, 1, 2] *)

How can I constrain the arguments to g such that it will accept either a pure function or a function defined with :=?

• There's no way to do this. I think you shouldn't. If you feel that you need a check, check that the result of applying the function is as expected. – Szabolcs Nov 7 '17 at 18:45
• There are countless very different looking expressions in Mathematica which can all be "called" as if they were a function. By trying to restrict your input, you will inevitably prevent the use of at least some of these. – Szabolcs Nov 7 '17 at 18:46
• – Alan Nov 7 '17 at 19:49
• @Alan, I was very hopeful when saw System'Private'MightEvaluateWhenAppliedQ in the page you linked to, but I could't get it to do anything. Every time I tried using it, I just got my expression back unevaluated. :( – ibeatty Nov 8 '17 at 20:49
• Try SystemPrivateMightEvaluateWhenAppliedQ[f], then f[x_] := x^2, then SystemPrivateMightEvaluateWhenAppliedQ[f] again. – Szabolcs Nov 10 '17 at 12:30

You may Condition the function pattern such that it matches for a parameter of Head Function or on the DownValues of the symbol when they have the pattern of that matches a basic function define by SetDelayed.

As pointed out in the OP comments there are many forms that a function can take and the solution below will not cover them all. However, it may be enough to cover the cases within your particular project.

With

ClearAll[g]
g[func_, a_, b_] /;
MatchQ[func, _Function] \[Or]
Length@Cases[DownValues[func][[All, 1]], \[FormalP] : HoldPattern[_[_Pattern .., ___]] :>
Hold@\[FormalP], 2] > 0 :=
func[a + b]

and

f[x_] := x^2 - 1

Then

g[f, 1, 2]
8
g[# + 1 &, 1, 2]
4
g[y, 1, 2]
g[y, 1, 2]

Hope this helps.

• This worked for me, but only after I removed the underscore after func in MatchQ[func_,_Function]. With the solution as written, I got an error about putting the pattern function on the right of a conditional. Also, you use foo_ in the argument list but func in the rest of the example; I presume that's just an oversight. – ibeatty Nov 8 '17 at 20:48
• @ibeatty Sorry, hasty change of variables as I realised you used func in your question and I had used foo in my notebook. Fixed. – Edmund Nov 8 '17 at 21:12
• @ibeatty Before you use this, consider things like InterpolatingFunction, CompiledFunction, the result of a LinearModelFit, functions defined with SubValues, e.g. add[x_][y_] := y+x, increment = add[1], and countless other examples. – Szabolcs Nov 10 '17 at 12:25