MathGroup Archive 1995

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Crossreference, code documentation

  • To: mathgroup at christensen.cybernetics.net
  • Subject: [mg1619] Re: Crossreference, code documentation
  • From: wagner at bullwinkle.cs.Colorado.EDU (Dave Wagner)
  • Date: Thu, 6 Jul 1995 23:12:59 -0400
  • Organization: University of Colorado, Boulder

In article <3t5fb2$8i5 at news0.cybernetics.net>,
 <larso171 at maroon.tc.umn.edu> wrote:

>Given that this simple exercise took me so much time, it seems wise to ask 
>around if there is a tool that does an even more complex job -- 
>providing a crossreference table of functions and the variables they use, 
>particularly global variables.

I have developed a function for the book that I'm writing
that I think might help you.  This function finds all symbols in an
expression without allowing anything to evaluate:

    In[1]:=
	SetAttributes[FindSymbols, HoldFirst]
	FindSymbols[expr_] :=
	Switch[Head[Unevaluated[expr]],
	    String | Integer | Real | Complex | Rational, {},
	    Symbol, {HoldForm[expr]},
	    _,  Union[Flatten[ReleaseHold[
				Map[FindSymbols,
				    Apply[List, Hold[expr], {1}],
				    {2}] ]],
		      FindSymbols @@ HeldPart[Hold[expr], 1, 0]
		]
	]

I'm not going to explain all the nuances of this function here (buy the
book when it comes out! :-)) but the basic idea is:  if what you're
looking at is an atom or a symbol, you're done; otherwise, recursively
descend into the expression by mapping FindSymbols onto all of the
parts of the expression, and the head itself.  The hard part is keeping
things from evaluating while doing all of this.

In the following example, all of the symbols have values, including those
in the head of the expression.

    In[3]:=
	{a,b,c, f, g} = {1,2,3, func1, func2};
	FindSymbols[f[a][b, g[c]]]
    Out[4]=
	{a, b, c, f, g}

The returned value is a list of symbols wrapped in HoldForm.

    In[5]:=
	InputForm[%]
    Out[5]//InputForm=
	{HoldForm[a], HoldForm[b], HoldForm[c], HoldForm[f], 
	  HoldForm[g]}

Now I started thinking about how you could apply this to your problem
and this is what I came up with.  First, let's define a function that
uses a few of these symbols and has more than one rule.

    In[6]:=
	h[x_] := a + f[b]
	h[x_,y_] := g[c]

    In[8]:=
	DownValues[h]
    Out[8]=
	{Literal[h[x_]] :> a + f[b], Literal[h[x_, y_]] :> g[c]}

We want to apply FindSymbols to the RHS of each of the above rules. Easy:

    In[9]:=
	Map[MapAt[FindSymbols, #, {2}]&, %]
    Out[9]=
	{Literal[h[x_]] :> FindSymbols[a + f[b]], 
	  Literal[h[x_, y_]] :> FindSymbols[g[c]]}

Slightly trickier: extracting the FindSymbols expressions from the delayed
rules, thus causing them to evaluate:

    In[10]:=
	% /. Literal[_ :> rhs_] -> rhs
    Out[10]=
	{{a, b, f, Plus}, {c, g}}

    In[11]:=
	Union[Flatten[%]]
    Out[11]=
	{a, b, c, f, g, Plus}

As soon as you have found a list of all symbols upon which each one of
your functions depends, you shouldn't have any problem inverting these
lists to find all functions that depend on any particular symbol.
"Left as an exercise for the reader." :-)

>I'm aware of the Names["Global*`"] command, which will give me a list of 
>all globals.  But I can't think of a simple way to find out which functions 
>use them or modify them.

Be careful not to confuse what's in the Global context with the concept
of "global variables".  In Mathematica, even local symbol names are in
the global context.  For example (starting with a fresh kernel):

    In[1]:=
	Names["Global`*"]
    Out[1]=
	{}

    In[2]:=
	f[x_] := Module[{y=2x}, y+z]

    In[3]:=
	Names["Global`*"]
    Out[3]=
	{f, x, y, y$, z}


		Dave Wagner
		Principia Consulting
		(303) 786-8371
		dbwagner at princon.com
		http://www.princon.com/princon


  • Prev by Date: Printing Problem
  • Next by Date: Re: Crossreference, code documentation
  • Previous by thread: Crossreference, code documentation
  • Next by thread: Re: Crossreference, code documentation