When making a project of significant size, a challenge that I sometimes encounter is remembering how all the functions that I’ve defined are related to one another. To address this, I’ve written the code below, which pulls from Names[“Global`*”] the functions I’ve defined, and makes a Graph of them based on which functions call which other functions.
​
In the toy example below, the definition for exampleFunc1[x_] calls on exampleFunc2, exampleFunc3, and exampleFunc4. So the Graph contains directed edges going from exampleFunc1 to 2, 3, and 4.
​
In the graph, you can hover over each function name to see a tooltip of its definition.
The primary difficulty that I encountered with coding this is that parsing Names[“Global`*”] seems to require some workarounds. That is because I’m identifying functions based on the occurrence of HoldPattern; but searching for HoldPattern produces nonstandard results. As a result, I convert the Names[] output to String and use StringReplace, which is not ideal. I would prefer to identify user-defined functions based on the structured Names[] output, but I couldn’t figure out how to do so without HoldPattern causing problems. Any advice here would be appreciated.
In[]:=
exampleFunc1[x_]:=Framed[exampleFunc2[x]+exampleFunc3[x]+exampleFunc4[x]]
In[]:=
exampleFunc2[x_]:=Framed[x]
In[]:=
exampleFunc3[x_]:=Framed[exampleFunc5[x]]
In[]:=
exampleFunc5[x_]:=Framed[x]
In[]:=
exampleFunc4[x_]:=Framed[exampleFunc6[x]+exampleFunc7[x]]
In[]:=
exampleFunc6[x_]:=If[x<=0,x,Framed[exampleFunc6[x-1]]]
In[]:=
exampleFunc7[x_]:=Framed[exampleFunc8[x]]
In[]:=
exampleFunc8[x_]:=Framed[exampleFunc9[x]]
In[]:=
exampleFunc9[x_]:=Framed[x]
In[]:=
globalFunctionList=​​Map[​​ToExpression[#,InputForm,DownValues]&​​,​​Names["Global`*"]​​];
In[]:=
globalFunctionList=​​Cases[​​globalFunctionList​​,​​List[RuleDelayed[name_HoldPattern,def_]]->{name,Hold[def]}​​];
In[]:=
globalFunctionList=​​Map[​​{​​ToString@InputForm@#[[1]],​​ToString@InputForm@#[[2]]​​}&​​,​​globalFunctionList​​];
In[]:=
globalFunctionList=​​Map[​​{​​StringReplace[#[[1]],"HoldPattern["~~fName__~~"["~~___~~"]]"->fName],​​#[[2]]​​}&​​,​​globalFunctionList​​];
In[]:=
globalFunctionList=​​Map[​​{​​#[[1]],​​StringReplace[#[[2]],"Hold["~~inner__~~"]"->inner]​​}&​​,​​globalFunctionList​​];
In[]:=
Grid[globalFunctionList,Frame->All]
Out[]=
exampleFunc1
Framed[exampleFunc2[x] + exampleFunc3[x] + exampleFunc4[x]]
exampleFunc2
Framed[x]
exampleFunc3
Framed[exampleFunc5[x]]
exampleFunc4
Framed[exampleFunc6[x] + exampleFunc7[x]]
exampleFunc5
Framed[x]
exampleFunc6
If[x <= 0, x, Framed[exampleFunc6[x - 1]]]
exampleFunc7
Framed[exampleFunc8[x]]
exampleFunc8
Framed[exampleFunc9[x]]
exampleFunc9
Framed[x]
In[]:=
functionPaths=​​Module[​​{allFuncNames,helperMakeEdges,paths}​​,​​allFuncNames=globalFunctionList[[All,1]];​​​​helperMakeEdges[funcName_]:=​​Module[​​{matches}​​,​​matches=Select[​​globalFunctionList​​,​​StringContainsQ[#[[2]],funcName]&​​];​​​​Map[​​DirectedEdge[#[[1]],funcName]&​​,​​matches​​]​​(*EndHelperModule*)​​];​​​​paths=helperMakeEdges/@allFuncNames;​​Flatten@paths​​​​(*EndModule*)​​];
In[]:=
functionPathsGraph=​​Module[​​{vertices,edges,helperVertexLabelFunction}​​,​​​​vertices=globalFunctionList[[All,1]];​​edges=functionPaths;​​​​helperVertexLabelFunction[v_]:=​​Module[​​{toolTipOptions}​​,​​toolTipOptions=​​{​​TooltipStyle->Directive[18,ShowStringCharacters->False,FontFamily->"Arial"]​​};​​​​Tooltip[​​ToString[v]​​,​​SelectFirst[​​globalFunctionList​​,​​ToString[#[[1]]]==ToString[v]&​​][[2]]​​,​​toolTipOptions​​]​​(*EndHelperModule*)​​];​​​​Graph[​​vertices​​,​​edges​​,​​VertexLabels->(v_:>helperVertexLabelFunction[v])​​]​​(*EndModule*)​​]

CITE THIS NOTEBOOK

Graphing relationships between user-defined function definitions​
by William H​
Wolfram Community, STAFF PICKS, January 15, 2025
​https://community.wolfram.com/groups/-/m/t/3356963