Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Functions inside modules with external definitions

227 views
Skip to first unread message

E. Martin-Serrano

unread,
Feb 14, 2009, 3:14:14 AM2/14/09
to
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


Jens-Peer Kuska

unread,
Feb 15, 2009, 3:19:51 AM2/15/09
to
Hi,

and my question is "Why do you use Module[] ?"

expression = a x^c + b y^(1 - c);

mx = Block[{f, expression = expression},


f[x_: x, y_: y][a_ : a, b_: b, c_: c] := Evaluate@expression;
f[k1, k2][.2, .3, .4]
]

work as expected.

Regards
Jens

David Bailey

unread,
Feb 15, 2009, 3:22:21 AM2/15/09
to
Evaluate is irrelevant to your problem - which is that you need to
replace the variables in your expression.

I would use a different symbol for the pattern variables:

g[xx_: x,yy_: y]:=(expression/.{x->xx,y->yy});

I am not sure why you require to define 'f' in such a complex way. There
may be easier ways to solve your underlying problem - I suggest you
describe what it is you want to do.

David Bailey
http://www.dbaileyconsultancy.co.uk


Leonid Shifrin

unread,
Feb 15, 2009, 3:21:06 AM2/15/09
to
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

E. Martin-Serrano

unread,
Feb 16, 2009, 7:00:12 AM2/16/09
to
Jens,

I use Module[] because the definition of f[] is inside a Module with a lot
of dynamic stuff (say 200 lines of code); and f[] (and other function
definitions, local to the module, are the root of all the dynamic treatment.
I never thought of Block as a construct or "container" for dynamic programs.
But maybe I was wrong.

Well, I tried many other approaches before posting but I did want to mess up
the example with other details.

I will review the other answers I have had, see what happens, and prepare a
full feedback if necessary. But, please, I would appreciate your remarks to
this as your solution works as needed. (Although, inside Block[]).

Regards

Emilio.

-----Original Message-----
From: Jens-Peer Kuska [mailto:ku...@informatik.uni-leipzig.de]
Sent: Sunday, February 15, 2009 9:20 AM
Subject: Re: Functions inside modules with external definitions

Hi,

and my question is "Why do you use Module[] ?"

expression = a x^c + b y^(1 - c);

mx = Block[{f, expression = expression},
f[x_: x, y_: y][a_ : a, b_: b, c_: c] := Evaluate@expression;

f[k1, k2][.2, .3, .4]
]

work as expected.

Regards
Jens

0 new messages