How can I check if a function parameter is another function defined with :=
f[n_] := n^2+1
g[fun_, n_] := fun[n]
g[f, 3]
Mathematica Stack Exchange is a question and answer site for users of Wolfram Mathematica. It only takes a minute to sign up.
Sign up to join this communityAs proposed by @Nasser, you can use DownValues
to check whether there are any SetDelayed
s (which are returned as RuleDelayed
) associated with the symbol, for example:
Clear[f, g, h];
f[n_] := n^2 + 1
h = 1;
g[fun_Symbol, n_] /; MemberQ[DownValues[fun], RuleDelayed[_, _]] :=
fun[n]
g[f, 3]
(* 10 *)
g[h, 3]
(* g[1, 3] *)
Note that you haven't defined very clearly what you mean by function, so the code above will not recognize other types of functions (like pure Function
or symbols with attribute NumericFunction
).
In the implicit use-case inferred from the toy example, I will suggest the following:
f[n_] := n^2 + 1
g::nofun = "`` should be a function.";
g[fun_, n_] := With[{res = fun[n]}, res /; FreeQ[res, fun]];
g[fun_, _] := Null /; (Message[g::nofun, fun]; False);
g[f, 3]
(* 10 *)
g[ff, 3]
g::nofun: ff should be a function.
(* g[ff, 3] *)
Note it "fails" on bizarre functions like the following, whereas a DownValues
approach would "succeed":
fff[n_Integer?OddQ] := 1 + fff[n - 1];
g[fff, 3]
g::nofun: fff should be a function.
(*g[fff, 3] *)
(Included just in case you might run into functions that partially evaluate. I don't know a way to determine whether an expression will completely evaluate to an expression not containing fun
that does not evaluate the expression. Something to consider if evaluating the expression fun[n]
might take an extremely long time and "fail".)
Note this approach also succeeds on subvalue functions:
ffff // ClearAll;
ffff[data_?VectorQ][vec_?VectorQ] := data . vec;
g[ffff[{0.4, 0.6}], {12, 4}]
(* 7.2 *)
(If you combine this with a "bizarre" type function, it may "succeed" when it should "fail." Bullet-proof your actual use-case as needed. It exceeds my personal time-constraints, and perhaps my skill, to give a general bullet-proof approach that handles all possible use-cases.)
Variations:
Instead of FreeQ[res, fun]
, one could test NumberQ[res]
, if "success" should only occur when the result is a number. Other tests may be substituted as appropriate.
Of course its easy to check eg
Definitions["Global`*"]
for occurences of "n_"] by inspection, but except for copy and paste, any attempt to store the result in a variable or even Export and Import as a text file gives nothing else but "Definitions["Global`*"]"
In the old days it was a simple way to save the actual definitions made, without overhead, before an evaluation crashed or hanged forever.
Now, going through memory instances I came to:
path="C:\\Users\\me\\desktop\\defs.txt";
Export[path, DownValues[In]]
dnt = Import[path, "String" ];
rec = StringSplit[dnt, "\n,"]
rec[[1]]
(StringDelete[#, "HoldPattern[In[" ~~ __ ~~ ":>" ] &) /@
StringSplit[Import[ins, "String"], {"\n"}]
Because I lost some really precious and large projects over the years, just by touching the wrong key or tapping the touchpad, I suggested to Wolfram some years ago, to store the naked users definition input in a backup file permanently in the temp directory as most text processors and even browsers do for. It seems that shielding of the system against reverse engeneering has priority.
Now in vs 13, with a new kind of unexplained suddden kernel shutdowns, its so more a necessity.
g[fun_Symbol, n_] /; MemberQ[DownValues[fun], RuleDelayed[_, _]] := fun[n]
$\endgroup$g[fun_, n_] /; ValueQ[fun, Method -> "SymbolDefinitionsPresent"] := fun[n]
? $\endgroup$