MathGroup Archive 1994

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

Search the Archive

Re: Question about function definitions

  • To: mathgroup at christensen.cybernetics.net
  • Subject: [mg279] Re: Question about function definitions
  • From: villegas (Robert Villegas)
  • Date: Sun, 4 Dec 1994 06:00:54 -0600

Scott,

   What you saw in your 'delay' function was an example of Mathematica
renaming the local variable of a function to prevent it from happening
to have the same name as another variable which is supposed to be
distinct and unrelated.

When you nest function definitions, the local variables of the inner one
will get renamed (by appending "$") any time the formula (i.e. the body)
of the inner one contains occurrences of the local variables of the outer
one.  For example, I define a command 'assign' that makes an assignment to
f.

In[1]:= assign[c_] := (f[x_] := c x)

f's formula, c x, contains c, which is the variable of 'assign'.
So when I do assign[-anything-], it will rename f's variable before
performing the assignment to f:

In[2]:= assign[3]

In[3]:= ? f
Global`f

f[x$_] := 3*x$


Now let's try a case where f's formula doesn't contain c:

In[3]:= Clear[assign, f]

In[4]:= assign[c_] := (Print[c]; f[x_] := x + x^2)

In[5]:= assign[3]
3

In[6]:= ? f
Global`f

f[x_] := x + x^2

No renaming was done this time.


   That's _what_ Mathematica does, but _why_ does it do that?  The idea
is that when you make a function definition, the variables are
supposed to be a dummy variables, meaning their names should have
no effect on the function's meaning, in any situation whatsoever.
You should be able to choose f[x_], or f[u_], or f[orange_] and
get the same function no matter what.

To see how easily that principle would get violated, suppose
Mathematica did not rename x to x$ each time I used the first
version of 'assign':

In[1]:= assign[c_] := (f[x_] := c x)

Now, this command is supposed to cause f to multiply its argument by c,
whatever c is.  If I call assign[3], then f should become a function
that multiplies its argument by 3, and it does.  But what if I wanted
f to be the function which multiplies its argument by the symbol x?
For instance, f[25] should return 25*x, and f[a] should return x*a.
A symbol is as good a coefficient as a number, so I should be able to
do this.  But without renaming, here is what I would get:

In[2]:= assign[x]

In[3]:= ? f
Global`f

f[x_] := x*x          (* hypothetical outcome:  WRONG *)

In[3]:= f[25]

Out[3]= 625           (* hypothetical outcome:  WRONG *)

f has become the squaring function!  This conflict has come about because
the user happened to choose the same symbol for the coefficient as what
I used for f's dummy variable.  Had I chosen used f[u_], then assign[x]
would cause no problem, but assign[u] would.  This situation is not
acceptable, because the names become meaningful, even if only in special
instances.


   Mathematica solves this problem by renaming the inner function's
variables to things that are unlikely to be employed by users:  the
original names suffixed with "$", as we saw.  Since f is using x$ for its
variable, the user can supply a coefficient of x and it will really be a
coefficient.

In[6]:= Clear[assign, f]

In[7]:= assign[c_] := (f[x_] := c x)

In[8]:= assign[x]

In[9]:= ? f
Global`f

f[x$_] := x*x$

In[9]:= f[25]

Out[9]= 25 x


Since the system is appropriating symbols that end in "$" for this
purpose, you should never make use of them yourself.  If you did
do assign[x$], you would intentionally create a name conflict, defeating
the mechanism.

The renaming stage does not check to see that an actual name conflict
has occurred, it just performs renaming if the potential is there.
Hence, for assign[3], the renaming turns out to be unnecessary.



Applying all this to your examples:

In your first example, the f[s_] definition inside 'delay' has
a T in it.  Since T is a local variable of the outer function
'delay', f's variables must be renamed.  It is a case of an outer
function possibly interfering with an inner one.

In your second example, the f[t_] definition inside the 'tes' function
has nothing but t in it, no occurrences of num, so renaming is
unnecessary.

tes[num_] := Module[{},
  f[t_] := Sin[t];
  For[k = 1, k <= num, k++,
    y = f';
    f[t_] = y[t - 2];
  ]
]


Robby Villegas
Wolfram Research





  • Prev by Date: Behaviour of TagUnset
  • Next by Date: Re: Pentium bug. Is it fixed?
  • Previous by thread: Behaviour of TagUnset
  • Next by thread: Mathematica as a Tool