1
$\begingroup$

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 *)
Head[f[x]] (* ==> Plus *)

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

$\endgroup$
  • 3
    $\begingroup$ 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. $\endgroup$ – Szabolcs Nov 7 '17 at 18:45
  • 4
    $\begingroup$ 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. $\endgroup$ – Szabolcs Nov 7 '17 at 18:46
  • 1
    $\begingroup$ See mathematica.stackexchange.com/questions/147942/… $\endgroup$ – Alan Nov 7 '17 at 19:49
  • $\begingroup$ @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. :( $\endgroup$ – ibeatty Nov 8 '17 at 20:49
  • $\begingroup$ Try System`Private`MightEvaluateWhenAppliedQ[f], then f[x_] := x^2, then System`Private`MightEvaluateWhenAppliedQ[f] again. $\endgroup$ – Szabolcs Nov 10 '17 at 12:30
1
$\begingroup$

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.

| improve this answer | |
$\endgroup$
  • $\begingroup$ 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. $\endgroup$ – ibeatty Nov 8 '17 at 20:48
  • $\begingroup$ @ibeatty Sorry, hasty change of variables as I realised you used func in your question and I had used foo in my notebook. Fixed. $\endgroup$ – Edmund Nov 8 '17 at 21:12
  • 1
    $\begingroup$ @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. $\endgroup$ – Szabolcs Nov 10 '17 at 12:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.