Mathematica 9 is now available
Services & Resources / Wolfram Forums / MathGroup Archive
-----

MathGroup Archive 2009

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

Search the Archive

Re: Functions inside modules with external definitions

  • To: mathgroup at smc.vnet.net
  • Subject: [mg96512] Re: [mg96494] Functions inside modules with external definitions
  • From: Leonid Shifrin <lshifr at gmail.com>
  • Date: Sun, 15 Feb 2009 03:21:12 -0500 (EST)
  • References: <200902140814.DAA17405@smc.vnet.net>

Hi,

The difficulty you are having is due  to the fact that the scoping
constructs (Module in particular) tend to rename the bound variables when
they feel a possibility for a name conflict. Perhaps, the question you are
asking is this: how to define a local function with variables automatically
bound to certain specific variables of an arbitrary expression on your rhs.

If this is really what you want, the solution is to make the binding of the
would-be-local function's variables  happening outside of the lexical scope
of the scoping constructs - in this case they won't be able to "spot" the
conflict at their own binding time. Anyway, here is the code:

In[1] =

(*  Auxilliary function   *)

Clear[optF];
optF[x_] := With[{xl = x}, Optional[Pattern[xl, Blank[]], xl]];


(* Bringing variable binding in the would-be-local function out of scope of
enclosing Module *)


Clear[makeFunction];
makeFunction[fn_, x_, y_, a_, b_, c_, rhs_] :=
  With[{optx = optF[x], opty = optF[y], opta = optF[a],
    optb = optF[b], optc = optF[c]},
   fn[optx, opty][opta, optb, optc] = rhs];

(*  Finally, what you want:  *)

Clear[compute];
compute[expr_] :=
 Module[{f},
  makeFunction[f, x, y, a, b, c, expr];
  f[k1, k2][.2, .3, .4]];

Test:

In[2] = compute[expression]

Out[2] =

0.2 k1^0.4 + 0.3 k2^0.6

I would also add that it would be less error prone to define your
<expression>
with SetDelayed rather than Set:

In[3]=expression:=a x ^c + b y ^(1-c)

And, finally, to wrap all your computation in a Block:

In[4] = Block[{x,y,a,b,c},compute[expression]]

Out[4] = 0.2 k1^0.4 + 0.3 k2^0.6,

to protect your computation from possible global values that
{x,y,a,b,c} may have.

You can test that on different expressions the result will be accordingly
different - perhaps this is what you asked for. Let me also remark that in
general, playing with binding and breaking the binding scope (by separating
the lhs and rhs into different parts of the program) is a pretty error-prone
practice, and there should be good reasons for doing it - there almost
always exist better design solutions. The whole fact that we have to "blind"
the scoping construct means that we are going in directions where we will
get no automatic support from the language.

Regards,
Leonid



On Sat, Feb 14, 2009 at 12:14 AM, E. Martin-Serrano <
eMartinSerrano at telefonica.net> wrote:

> Hi,
>
>
>
> Please review the following and see weather my question has and deserves an
> answer. It is a about defining functions local to modules but using
> external
> definitions of the right hand side of the local function and passed as
> parameters to the module.
>
>
>
>
>
> expression = a x ^c + b y ^(1-c)  (* or whatever expression *)
>
>
>
> Clear[f];
>
>
>
> f[x_: x,y_: y][a_: a,b_: b,c_: c]:=Evaluate@expression
>
>
>
> ?f
>
> f[k1,k2][.2,.3,.4]
>
>
>
> (* Functions inside modules where the RHS of the function has been assigned
> to a variable *)
>
> (* first form works as I expected, but uses an extrenal definition for a
> local function (the name is local) *)
>
>
>
> m1=
>
>  Module[{f},
>
>  f[x_: x,y_: y][a_ :a,b_: b,c_: c]:=Evaluate@expression;
>
>  f[k1,k2][.2,.3,.4]
>
>  ]
>
>
>
> (* second form.  I expected it worked as the one above but it does not; the
> expression formed outside is assigned to a local variable with the same
> name
> *)
>
>
>
> m2 =
>
>  Module[{f, expression = expression},
>
>  f[x_: x, y_: y][a_ :a,b_: b,c_: c]:=Evaluate@expression;
>
>  f[k1,k2][.2,.3,.4]
>
>  ]
>
>
>
> (* third form. I expected it worked as the first one above but it does not;
> the expression is assigned directly to a local variable *)
>
>
>
> m3 =
>
>  Module[{f,expression = a x ^c + b y ^(1-c)},
>
>  f[x_: x,y_: y][a_ :a,b_: b,c_: c]:=Evaluate@expression;
>
>  f[k1,k2][.2,.3,.4]
>
>  ]
>
>
>
> (* fourth form. I expected it worked as the first one above but it does
> not;
> the expression is assigned within the body of the module o a local variable
> *)
>
>
>
> m4 =
>
>  Module[{f,expr},
>
>  expr =expression;
>
>  f[x_: x,y_: y][a_ :a,b_: b,c_: c]:=Evaluate@expr;
>
>  f[k1,k2][.2,.3,.4]
>
>  ]
>
>
>
> (* My question is how to construct a function inside a module in manner
> similar to the following *)
>
>
>
> expression = a x ^c + b y ^(1-c);
>
> mx =
>
>  Module[{f,expression = expression},
>
>  f[x_: x,y_: y][a_ :a,b_: b,c_: c]:=Evaluate@expression;
>
>  f[k1,k2][.2,.3,.4]
>
>  ]
>
>
>
> (* and working as the following works *)
>
>
>
> m1=
>
>  Module[{f},
>
>  f[x_: x,y_: y][a_ :a,b_: b,c_: c]:=Evaluate@expression;
>
>  f[k1,k2][.2,.3,.4]
>
>  ]
>
>
>
> Many thanks
>
>
>
>
>
> E. martin-Serrano
>
>
>


  • Prev by Date: optimization
  • Next by Date: Re: Re: Dynamic changing of variables
  • Previous by thread: Functions inside modules with external definitions
  • Next by thread: Re: Functions inside modules with external definitions