MathGroup Archive 1997

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

Search the Archive

Re: Procedure to Function

  • To: mathgroup at smc.vnet.net
  • Subject: [mg8236] Re: Procedure to Function
  • From: Robert Villegas <villegas>
  • Date: Thu, 21 Aug 1997 21:16:53 -0400
  • Sender: owner-wri-mathgroup at wolfram.com

Robert Pratt asked why turning this procedure:


> PROCEDURE
> 
> Clear[u, v, x, y, g]
> u = x^3 - 3 x y^2 + y;
> v[x_, y_] := Integrate[D[u,x],y] + g[x];
> g[x_] := Evaluate[g[x] /.DSolve[D[v[x, y],x] == D[u,y], g[x], x][[1]]];
> v[x, y]
> 
> -x + 3 x^2 y - y^3 + C[1]


into this function:


> FUNCTION
> 
> Clear[u, v, x, y, g, HarmonicConjugate]
> HarmonicConjugate[u_] :=
>   (v[x_, y_] := Integrate[D[u,x],y] + g[x];
>   g[x_] := Evaluate[g[x] /.DSolve[D[v[x, y],x] == D[u,y], g[x],  
> x][[1]]];
>   v[x, y])
> HarmonicConjugate[x^3 - 3 x y^2 + y]


did not work.


Allan Hayes offered a solution that works for this problem:


> A general way of avoiding this kind of problem is to prevent the  
> direct substition. Thus:
> 
> Clear[u, v, x, y, g, HarmonicConjugate]
> 
> HarmonicConjugate[u_] :=
>   (uu=u;
>                 v[x_, y_] := Integrate[D[uu,x],y] + g[x];
>   g[x_] := Evaluate[g[x] /.DSolve[D[v[x, y],x] == D[uu,y], g[x],  
> x][[1]]];
>   v[x, y])


This won't work in general, because it relies on uu getting evaluated
wherever it is used.  It's fine in your example, but other code might
contain functions like Plot and FindRoot that hold their arguments, or
might use held expressions to construct something.  For these cases, which
aren't that infrequent, giving uu an initial value and using it instead of
u in the code isn't the same as directly substituting the passed value of
u into the code.

The more general work-around is to have your code disguise function
definitions (and any other scoping constructs that use u).  Although it's
a tad verbose, it's not too bad -- just replace every

   lhs := rhs

with

   SetDelayed @@ HoldComplete[lhs, rhs]

in your code (use Hold instead of HoldComplete if you don't have
Mathematica 3.0 yet).

In[10]:=
Clear[u, v, x, y, g, HarmonicConjugate]
HarmonicConjugate[u_] :=
  (SetDelayed @@ HoldComplete[v[x_, y_], Integrate[D[u,x],y] + g[x]];
  SetDelayed @@ 
      HoldComplete[g[x_], 
        Evaluate[g[x] /.DSolve[D[v[x, y],x] == D[u,y], g[x],  
x][[1]]]];
  v[x, y])

In[12]:=
HarmonicConjugate[x^3 - 3 x y^2 + y]

Out[12]=
       2      3
x - 3 x  y - y  + C[1]



   For debugging these problems, here is an alternative to Trace.
Any time you have a function definition

   f[x_, y_, ...] := stuff

you can find out what 'stuff' becomes after the values of x, y, etc. are
substituted in, without actually running the code in 'stuff'.  Merely wrap
HoldForm around the right-hand side:

   f[x_, y_, ...] := HoldForm[stuff]

Then call f with whatever arguments you want, and you can see what really
would have gotten evaluated.  Example:

HarmonicConjugate[u_] :=
HoldForm[
  v[x_, y_] := Integrate[D[u,x],y] + g[x];
  g[x_] := Evaluate[ g[x] /. DSolve[D[v[x, y],x] == D[u,y],
    g[x],x][[1]] ];
  v[x, y]
]


It reveals a lot:

In[99]:=
HarmonicConjugate[x^3 - 3 x y^2 + y]

Out[99]=
                            3            2
v[x$_, y$_] := Integrate[D[x  + y - 3 x y , x$], y$] + g[x$]; 
 
  g[x$_] := Evaluate[g[x$] /. 
 
                                  3            2
     DSolve[D[v[x$, y], x$] == D[x  + y - 3 x y , y], g[x$], x$][[1]]
 
     ]; v[x, y]

Now it's obvious that the pattern variables of the functions aren't the
same as the variables in the expression passed in.



Allen's second solution:

> Here is another function, though it does not include the arbitrary  
> constant in the result,
> 
> HarmonicConjugate2[u_,{x_,y_}]:=
>         (# + Integrate[-D[#,x]-D[u,y],x])&[Integrate[D[u,x],y]]

hints at a design flaw in the design of the original function.  The
original function required that the expression be in terms of
variables called 'x' and 'y'.  In general, it's bad practice to hard-code
the variable names; it's more versatile if function takes the variables as an
additional argument, like Integrate or Plot does.  That way, a^3 - 3 a b^2 + b
will work as well as x^3 - 3 x y^2 + y.  You can still have the convenience
of assuming 'x' and 'y' if the variables are omitted.


HarmonicConjugate3[u_] := HarmonicConjugate3[u, {x, y}]

HarmonicConjugate3[u_, {x_, y_}] :=
Module[{v, g},
  v[x_, y_] := Integrate[D[u, x], y] + g[x];
  g[x_] = g[x] /. DSolve[D[v[x, y], x] == D[u, y], g[x], x][[1]];
  v[x, y]
]


Making v and g local variables instead of global is useful because if you
keep making corrections to this code, you won't have a pile-up of
mistaken definitions to v and g.  And you're guaranteed they won't
interfere with other v and g.


In[6]:=
HarmonicConjugate3[x^3 - 3 x y^2 + y]

Out[6]=
       2      3
x - 3 x  y - y  + C[1]

In[7]:=
HarmonicConjugate3[x^3 - 3 x y^2 + y, {x, y}]

Out[7]=
       2      3
x - 3 x  y - y  + C[1]

In[8]:=
HarmonicConjugate3[a^3 - 3 a b^2 + b, {a, b}]

Out[8]=
       2      3
a - 3 a  b - b  + C[1]



Robby Villegas


  • Prev by Date: Re: Limit a^n / n!
  • Next by Date: Re: Re: floor problems
  • Previous by thread: Re: Procedure to Function
  • Next by thread: RE: Expanding function names to