# 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] *)


Checking the Head of f doesn't seem helpful:

Head[f] (* ==> Symbol *)


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. Nov 7, 2017 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. Nov 7, 2017 at 18:46
• – Alan
Nov 7, 2017 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. :( Nov 8, 2017 at 20:49
• Try SystemPrivateMightEvaluateWhenAppliedQ[f], then f[x_] := x^2, then SystemPrivateMightEvaluateWhenAppliedQ[f] again. Nov 10, 2017 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. Nov 8, 2017 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. Nov 8, 2017 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. Nov 10, 2017 at 12:25