1
$\begingroup$

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]
$\endgroup$
9
  • 3
    $\begingroup$ I have noticed you have now already posted 5 questions which got multiple answers but you haven't accepted any of them. Please accept the best answers by clicking on the checkmark (✓) next to them. $\endgroup$
    – Domen
    Apr 20 at 8:02
  • 2
    $\begingroup$ Excuse me, I didn't know that and I'll fix it $\endgroup$ Apr 20 at 8:15
  • 2
    $\begingroup$ What about something like this (as proposed by @Nasser): g[fun_Symbol, n_] /; MemberQ[DownValues[fun], RuleDelayed[_, _]] := fun[n] $\endgroup$
    – Domen
    Apr 20 at 9:50
  • 1
    $\begingroup$ Related (including threads linked therein): stackoverflow.com/questions/3736942/… $\endgroup$
    – Lukas Lang
    Apr 20 at 18:04
  • 2
    $\begingroup$ how about g[fun_, n_] /; ValueQ[fun, Method -> "SymbolDefinitionsPresent"] := fun[n]? $\endgroup$
    – kglr
    Apr 20 at 19:43

3 Answers 3

4
$\begingroup$

As proposed by @Nasser, you can use DownValues to check whether there are any SetDelayeds (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).

$\endgroup$
0
$\begingroup$

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.

$\endgroup$
-1
$\begingroup$

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.

$\endgroup$

Your Answer

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

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