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