Re: removing those annoying $$$$'s from local variables names?
- To: mathgroup at smc.vnet.net
- Subject: [mg79719] Re: removing those annoying $$$$'s from local variables names?
- From: Albert <awnl at arcor.net>
- Date: Thu, 2 Aug 2007 03:58:37 -0400 (EDT)
- References: <f8pk78$2i1$1@smc.vnet.net>
Hi,
> This problem is when a function returns back a symbol which is local
> to the function,
> This is an example:
>
> ------------- example 1 -------------
>
> foo[] := Module[{c, k},
> c = Array[k, 3]
> ];
>
> c = foo[];
> Print[c];
>
> {k$76[1], k$76[2], k$76[3]}
> --------------------------------------------------
>
> You see, since k is local to foo[], then when I print it, I see those $
> $$ signs.
to be precise the symbols are not local to the function foo but to the
Module...
> Only way to remove this $$$'s is to make k global as follows
Be sure that there are another 1000 ways to "remove" them :-)
> ------------------------ example 2 -------------------
> Remove[k];
> foo[] := Module[{c},
> c = Array[k, 3]
> ];
>
> c = foo[];
> Print[c];
>
> {k[1], k[2], k[3]}
> ----------------------------------------
>
> But making 'k' global is something I do NOT want to do, since now I
> have to worry about 'k' having a value somewhere else in the code, and
> it goes against the whole idea of encapsulation.
Honestly, I think returning expressions that contain these local symbols
is against the whole idea of encapsulation in the first place...
> If I start making all
> my symbols global, then the code becomes hard to manage.
very true, you should absolutely use local variables as much as possible...
> So, what should one do in this case? How can make all the symbols
> local to a function, but at the same time not see these $$$'s when the
> symbols are used when they are returned from the function back to the
> caller?
the problem you have is that when returning "local" symbols they need to
have different names than the possibly existing globals, otherwise there
is nor chance to separate them once you leave the Module. Try to use
Block instead of Module and you will see that localization does not make
sense (unless you want the special behaviour of the following code) when
returning the local symbols with names that already exist as globals:
In[32]:= k = 15
Block[{k, a}, a = Array[k, 3]; Print[a]; a]
Out[32]= 15
(* the follwing is the result of the Print *)
During evaluation of In[32]:= {k[1], k[2], k[3]}
Out[33]= {15[1], 15[2], 15[3]}
One thing you can do is to only make the local symbols look simpler in
output but still have the names, like this:
In[34]:= res = Module[{k}, Format[k] = "k";
Array[k, 3]]
Out[34]= {"k"[1], "k"[2], "k"[3]}
you won't see the "" in the notebook interface with default settings.
But note that:
In[35]:= InputForm[res]
Out[35]//InputForm=
{k$444[1], k$444[2], k$444[3]}
so something like:
res/.k->kk
will not work. If all that happens to the returned expression is
printing this might solve your issue. If that is the case and k is just
used as a label, you could return an expression with strings in the
first place, which is rather simple and robust (and makes the Module
superfluous, by the way):
Module[{},Array["k",3]]
It is not entirely clear to me what you want to do and if these are
reasonable "solutions" to your problem. After all it is quite obscure to
most users when these k's are now different than there representation or
are strings and not symbols. Maybe it would be a good idea if you'd
explain what you want to achieve. I can hardly believe that there are
not better methods to do what you probably want than to return those
local symbols as output. One thing that I often do is to return a
function object rather than an expression, which solves the problem of
"which kind of symbol should be in that expression" quite neatly:
In[30]:= res = Module[{k}, Function @@ {{k}, Array[k, 3]}]
Out[30]= Function[{k$440}, {k$440[1], k$440[2], k$440[3]}]
Note that I needed to use a trick to enforce evaluation of the function
body and avoid additional scoping by Function...
Now in the calling code you can choose what the name of the symbol in
the returned expression should be (and e.g. use symbol which is local in
the calling module), like in:
In[31]:= res[myk]
Out[31]= {myk[1], myk[2], myk[3]}
or for pretty printing even insert a string:
Print[res["k"]]
{"k"[1], "k"[2], "k"[3]}
Another option is to use an additional argument so that again the
calling code can define which symbol should be used:
foo[sym_]:=Array[sym,3]
foo[k]
hth,
albert