2
$\begingroup$

I'm working on a package with a lot of functions using Module, which all begin by unpacking the arguments into local variables. I'd like to store this unpacking code in a separate function called Setup and just call it in each function, but the local variables don't make it out.

A simple example:

Setup := (z = x^2);

g[x_] := Module[{z},
Setup;
Return[z]
];

g[3]

returns z$2599 when I'd like it to return 9. My real Setup is much longer of course, which is why I'd rather recycle it than rewrite it in each function.

Is there an easy way to make this work?

Update: A less minimal example

Here's a slightly less minimal example that captures more of the real situation. In my real problem, the Setup code is about a page long. At this point, I'm too far into this to change how I store the z[i] to a list!

Setup := (
numX = Length[x];
Do[z[i] = StringLength[x[[i]]], {i, numX}]
)

g[x_List] := Module[{numX, z},
Setup;
Table[z[i], {i, numX}]
]

g[{"hi", "there"}] should return {2,5}.

$\endgroup$
  • 1
    $\begingroup$ Please,can you clarify the question ? What's wrong with something like: setup[param_(*if required*),x_]:=x^2; g[x_]:=Module[{ret,z}, z=setup[param,x]; ret=f[z](*if required*); Return[ret] ]; g[3] $\endgroup$ – mitochondrial Feb 22 '16 at 20:36
  • 1
    $\begingroup$ You're scratching your left ear with your right hand (Spanish saying) $\endgroup$ – Dr. belisarius Feb 22 '16 at 21:01
  • 1
    $\begingroup$ @Dr.belisarius, interestingly, there is the same saying in Russian. $\endgroup$ – garej Feb 22 '16 at 21:17
  • 1
    $\begingroup$ @garej I guess that's because of the gauge invariance of the human body :) $\endgroup$ – Dr. belisarius Feb 22 '16 at 21:19
  • $\begingroup$ @Szabolcs Out of curiosity, why shouldn't you use Return at the end of a Module? Even though unnecessary, it helps me easily spot what's being returned at the end of a long Module. $\endgroup$ – Chris K Feb 22 '16 at 22:16
4
$\begingroup$

The thing to do is pass the parameters to setUp and make that function hold its arguments.

SetAttributes[setUp, HoldAll]
setup[z_, numX_, x_] := (numX = Length[x];
  Do[z[i] = StringLength[x[[i]]], {i, numX}])

g[x_List] := Module[{numX, z},
  setup[z, numX, x];
  Table[z[i], {i, numX}]]

g[{"hi", "there"}]

(* Out[1016]= {2, 5} *)
$\endgroup$
1
$\begingroup$

Why don't you use a function for it?

setup[x_, y_] := {x^2 - y, y*x^3}
f[args___] := 
    Module[{u,v},
        {u,v} = setup[args];
        u + v
    ]

I showed this to prove that the code can be concise but I would write out the arguments of f explicitly as f[x_, y_] instead of f[args___] to restrict the forms that match.

$\endgroup$
  • $\begingroup$ The real Setup is more complicated and involves setting an a priori unknown number of local variables using DownValues (i.e. setting z[1], z[2], ... ). $\endgroup$ – Chris K Feb 22 '16 at 20:37
  • $\begingroup$ @ChrisK It sounds like you should update the question and explain the use case better (and also motivate why you need DownValues instead of an array). $\endgroup$ – Szabolcs Feb 22 '16 at 20:39
  • $\begingroup$ @ChrisK It is possible to splice that piece of code (Setup) directly into the definition of g, but that is an error-prone advanced operation that should really be used only as a last resort ... The topic is covered in some detail here. I would not go that route unless I am really really sure that there is no better alternative. $\endgroup$ – Szabolcs Feb 22 '16 at 20:47
  • $\begingroup$ Thanks for the leads. At this point I've got too much code to change how I store the processed values. $\endgroup$ – Chris K Feb 22 '16 at 20:50
  • 3
    $\begingroup$ @ChrisK How about something like this (untested)? pastebin.com/dVx0p2ph $\endgroup$ – Szabolcs Feb 22 '16 at 20:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.