6
$\begingroup$

Is it possible to obtain all user defined definitions (and attributes) that are used in the evaluation of certain command (or alternatively just their symbols which I could imagine being easier when symbols carry both used and unused definitions/attributes). I want to use this in order to quickly be able to share a minimal amount of code required to make a certain command run correctly.

Minimal example:

f[x_] := 3;
traceUserDefinedDefinitions[f[4]];

would return {"f[x_]:=3"} (or some equivalent format).

$\endgroup$
4
  • $\begingroup$ How would you share this code? $\endgroup$
    – Carl Woll
    Aug 21, 2023 at 14:22
  • $\begingroup$ @Carl, I would like to share a notebook. Some editing might of course be required afterwards to make the code shareable but I would like to automatically generate a notebook that at least requires all the code required to run the command of interest. $\endgroup$
    – Kvothe
    Aug 21, 2023 at 14:24
  • $\begingroup$ @Syed. The example was perhaps too simple. I meant of course that f might contain calls to many other user defined functions. However, it seems that FullDefinition might simply give what I need. $\endgroup$
    – Kvothe
    Aug 21, 2023 at 14:28
  • $\begingroup$ I removed my comment that proposed Information[f] after realizing that you had a more complicated task at hand. $\endgroup$
    – Syed
    Aug 21, 2023 at 14:41

2 Answers 2

7
$\begingroup$

You can use the framework that Wolfram cloud uses to transfer content:

CreateNotebookDefinition[f_]:=With[{def=Language`ExtendedFullDefinition[f]},
    CreateDocument[ExpressionCell[Defer[Language`ExtendedFullDefinition[f] = def], "Input"]]
]

Using CreateNotebookDefinition will create a notebook with an input cell that will recreate the desired definitions.

$\endgroup$
5
$\begingroup$

A primitive start would be to simply use Trace, and then look for all user-defined symbols that appear.

Clear["Global`*"];
a = 7;
f[x_] := 3 x^2;
g[x_, y_] := f[2 x];
h[x_] := Sqrt[f[x] - g[x, 5 x] - a];
i[x_, y_] := Exp[-x + y];

SetAttributes[traceUserDefinedDefinitions, HoldFirst];
traceUserDefinedDefinitions[expr_] := 
 DeleteDuplicates@
  Cases[Trace[expr, TraceOriginal -> True], 
   Alternatives @@ (ToExpression[Names["Global`*"], InputForm, 
      HoldForm]), All]

traceUserDefinedDefinitions[h[4]]
(* {h, f, g, a} *)

You may then use @Carl Woll's answer (or some other way to obtain full definitions of symbols) to export definitions to a new notebook:

CreateNotebookDefinition[traceUserDefinedDefinitions[h[4]]]
$\endgroup$
3
  • $\begingroup$ Note that Language`ExtendedFullDefinition already finds dependent symbols (this is what the Full means), so it is not necessary to use your traceUserDefinedDefinitions function $\endgroup$
    – Carl Woll
    Aug 21, 2023 at 15:29
  • $\begingroup$ @CarlWoll, imagine a = 1; g[x_] := x;. One cannot use only your method to determine that running g[a] requires the definition of a, right? Namely, Language`ExtendedFullDefinition[g] will not include a. $\endgroup$
    – Domen
    Aug 21, 2023 at 15:36
  • $\begingroup$ If the intention (unclear) is to have definitions so that evaluating an expression (that contains multiple symbols) will work, then you are correct. Still., it would be simpler to just find all symbols in the expression, and then use Language`ExtendedFullDefinition on them instead of using Trace. $\endgroup$
    – Carl Woll
    Aug 21, 2023 at 15:45

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.