Re: function local/private to another function?
- To: mathgroup at smc.vnet.net
- Subject: [mg110599] Re: function local/private to another function?
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Sun, 27 Jun 2010 04:56:28 -0400 (EDT)
Hi Nasser, > What is the best way to have a function which can only be "seen" and > called by only the enclosing parent function? And not be in the global > space (without using a package?). > > You first guess is right on target: f1[x_]:=Module[{b,f2}, .... f2[y_]:=Module[{c},...c=y^2... > > Return[x]]; > b=f2[x] > ... > ] does exactly what you want. <c> is indeed local to <f2> and not to <f1>. Moreover, you can use some of the variables local to <f1> inside <f2>, then <f2> will become what is usually called a closure - a function that grabs its surrounding environment, a very useful thing. One of the many reasons to use it is that you can return it from the external Module, and it will keep track of the environment surrounding it at the time of its creation long after that environment itself is gone (we exit external Module). This allows new ways of organizing the code, since you get a light-weight and cheap state encapsulation without the rest of the OOP boilerplate and associated with it tedium. If you do use some of the local variables of <f1> directly in <f2>, you can also do it in two different ways: using their names directly (and then your f2 will be able to change the original variables in the future), or embedding their values using With[{myvar = ...},f2[...]:=...], in which case you embed an immutable screenshot of the surrounding environment. Depending on the situation, you may find that you need the first or the second method. Regarding your puzzlement with f1[x_]:=Module[{c,f2}, .... f2[y_]:=Module[{c},...]; This happens because naming local variables the same way causes the name conflict in nested scoping constructs. In most cases (including this one), such conflicts do not represent the error per se, but rather the warning that the variable binding is subject to certain name conflict resolution rules and may be not what you may expect in some cases. Again, in most cases (including this one) such conflicts are resolved in favor of the inner scoping construct, so for example: f1[x_] := Module[{c = 2, f2}, f2[y_] := Module[{c = 1}, Print[c]]; f2[1] ]; f1[3] 1 For your use case, then, it will work correctly, if you can live with the annoying red coloring - otherwise just use different names for variables. I Wanted to find what is the best way to have a local function, with its > own local variables inside a parent function, where the only interaction > between the inner function and the parent function is via the argument > call. I looked at Block and With, but they do not do what I need. Regarding Block and With, you are right that they won't help you to make a local DownValues (OwnValues,UpValues, SubValues,etc) - based pattern-defined function - you really need to create a new symbol with a local lexical scope for the name of your function, and this is exactly what Module does. Block and With OTOH do not create new symbols. With Block, you will have a local function in a way, but for the price that the original symbol with the same name is shadowed and can not be referenced within the scope of Block, which is dynamic, so we are talking about the part of the execution stack - the scope of Block is in time rather than in space, in a way. This is often useful, but under different circumstances, and will give not what you probably had in mind. > I > think Module is the only choice left? Or should I not bother about > having local functions to another functions at all and leave everything > in the global space? > > Well, you can use Unique to simulate lexical scoping yourself, but Module has several advantages (two major ones IMO being automatic name conflicts resolution and automatic garbage collection of local symbols which are not referenced outside of the defining Module scope), so I would go with Module - this is a good way I think ( I use this all the time anyway) . Yet another way is to use pure functions, which you can assign to local variables. For example: Clear[f1]; f1[x_] := Module[{c = 2, f2 = Function[y, Module[{c = 1}, Print[c + y]]]}, f2[x]]; f1[3] 4 In such a construct, With could be used instead of external Module with the similar effect. Of course, such local functions will have all the limitations of the pure functions (no pattern-based definitions, no easy argument checks, no multiple definitions). Generally, I recommend you to follow this thread: http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/5eff6213a0ab5f51/29f3c90fe11b4926 particularly, my third post there, where I discuss these sort of constructs rather extensively and give references to a few more threads on similar topics that I am aware of. Hope this helps. Regards, Leonid --0015174482ce4c27790489f12b41 Content-Type: text/html; charset="ISO-8859-1" Content-Transfer-Encoding: quoted-printable X-Sun-Content-Length: 6084 Hi Nasser,<br><div class="gmail_quote"><br><blockquote class="gmail_quo= te" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt= 0.8ex; padding-left: 1ex;"> <br> What is the best way to have a function which can only be "seen" = and<br> called by only the enclosing parent function? And not be in the global<br> space (without using a package?).<br> <br> </blockquote><div>You first guess is right on target: <br> <br> f1[x_]:=Module[{b,f2},<br> ....<br> f2[y_]:=Module[{c},...c=y^2... <blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, = 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Return[x]];<br> b=f2[x]<br> ...<br> ]</blockquote><div> </div> <br> does exactly what you want. <c> is indeed local to <f2> and not to <f1>. Moreover, you can use some of the variables local to <f1> inside <f2>, then <f2> will become what is usually called a closure - a function that grabs its surrounding environment, a very useful thing. One of the many reasons to use it is that= you can return it from the external Module, and it will keep track of the = environment surrounding it at the time of its creation long after that envi= ronment itself is gone (we exit external Module). This allows new ways of o= rganizing the code, since you get a light-weight and cheap state encapsulat= ion without the rest of the OOP boilerplate and associated with it tedium. = <br> <br>If you do use some of the local variables of <f1> directly in <= ;f2>, you can also do it in two different ways: using their names direct= ly (and then your f2 will be able to change the original variables in the f= uture), or embedding their values using With[{myvar = ...},f2[...]:=...= ], in which case you embed an immutable screenshot of the surrounding envir= onment. Depending on the situation, you may find that you need the first or= the second method. <br> <br> Regarding your puzzlement with <br> <br> f1[x_]:=Module[{c,f2},<br> ....<br> f2[y_]:=Module[{c},...];<br> <br> This happens because naming local variables the same way causes the name conflict in nested scoping constructs. In most cases (including this one), such conflicts do not represent the error per se, but rather the= warning that the variable binding is subject to certain name conflict reso= lution rules and may be not what you may expect in some cases. Again, in mo= st cases (including this one) such conflicts are resolved in favor of the inner scoping construct, so for example:<br> <br> f1[x_] :=<br> Module[{c = 2, f2},<br> f2[y_] :=<br> Module[{c = 1}, Print[c]];<br> f2[1]<br> ];<br> <br> f1[3]<br> <br> 1<br> <br> For your use case, then, it will work correctly, if you can live with the annoying red coloring - otherwise just use different names for variables. <br><br></div><blockquote class="gmail_quote" style="border-left: 1px s= olid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> I Wanted to find what is the best way to have a local function, with its<br= > own local variables inside a parent function, where the only interaction<br= > between the inner function and the parent function is via the argument<br> call. I looked at Block and With, but they do not do what I need. </blockqu= ote><br><div><br>Regarding Block and With, you are right that they won'= t help you to make a local DownValues (OwnValues,UpValues, SubValues,etc) - based p= attern-defined function - you really need to create a new symbol with a local lexical scope for the name of your function, and this is exactly wh= at Module does. Block and With OTOH do not create new symbols. <br><br>With Block, you will have a lo= cal function in a way, but for the price that the original symbol with the = same name is shadowed and can not be referenced within the scope of Block, = which is dynamic, so we are talking about the part of the execution stack -= the scope of Block is in time rather than in space, in a way. This is ofte= n useful, but under different circumstances, and will give not what you pro= bably had in mind.<br> </div><blockquote class="gmail_quote" style="border-left: 1px solid = rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">I<br> think Module is the only choice left? Or should I not bother about<br> having local functions to another functions at all and leave everything<br> in the global space?<br> <br></blockquote><div><br>Well, you can use Unique to simulate lexical scop= ing yourself, but Module has several advantages (two major ones IMO being a= utomatic name conflicts resolution and automatic garbage collection of loca= l symbols which are not referenced outside of the defining Module scope), s= o I would go with Module - this is a good way I think ( I use this all the = time anyway) . Yet another way is to use pure functions, which you can assi= gn to local variables. For example:<br> <br>Clear[f1];<br>f1[x_] :=<br> Module[{c = 2, f2 = Function[y, Mo= dule[{c = 1}, Print[c + y]]]},<br> f2[x]];<br><br>f1[3]<br>4<br><br= >In such a construct, With could be used instead of external Module with th= e similar effect. Of course, such local functions will have all the limitat= ions of the pure functions (no pattern-based definitions, no easy argument = checks, no multiple definitions).<br> <br>Generally, I recommend you to follow this thread:<br><br><a href="htt= p://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/th= read/5eff6213a0ab5f51/29f3c90fe11b4926">http://groups.google.com/group/comp= .soft-sys.math.mathematica/browse_thread/thread/5eff6213a0ab5f51/29f3c90fe1= 1b4926</a><br> <br>particularly, my third post there, where I discuss these sort of constr= ucts rather extensively and give references to a few more threads on simila= r topics that I am aware of.<br><br>Hope this helps.<br><br>Regards,<br> Leonid<br><br> </div></div><br> --0015174482ce4c27790489f12b41--