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

1 Answer 1

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.

$\endgroup$
3
  • $\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, 2017 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, 2017 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, 2017 at 12:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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