2

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}.

Chris K
  • 20,207
  • 3
  • 39
  • 74
  • 1
    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] – mitochondrial Feb 22 '16 at 20:36
  • 1
    You're scratching your left ear with your right hand (Spanish saying) – Dr. belisarius Feb 22 '16 at 21:01
  • 1
    @Dr.belisarius, interestingly, there is the same saying in Russian. – garej Feb 22 '16 at 21:17
  • 1
    @garej I guess that's because of the gauge invariance of the human body :) – Dr. belisarius Feb 22 '16 at 21:19
  • @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. – Chris K Feb 22 '16 at 22:16
  • @ChrisK Well, I shouldn't have said "shoulnd't" and I'll retract it ... I won't have any bad effects other than a (tiny) performance hit. Some beginners always put it there because they don't understand that it is not necessary, but you are not a beginner. If it makes the code more readable to you then use it. – Szabolcs Feb 22 '16 at 22:34
  • Should work if you use Block instead of Module. – CalculatorFeline Feb 23 '16 at 04:47

2 Answers2

4

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} *)
Daniel Lichtblau
  • 58,970
  • 2
  • 101
  • 199
1

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.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
  • 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], ... ). – Chris K Feb 22 '16 at 20:37
  • @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). – Szabolcs Feb 22 '16 at 20:39
  • @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. – Szabolcs Feb 22 '16 at 20:47
  • Thanks for the leads. At this point I've got too much code to change how I store the processed values. – Chris K Feb 22 '16 at 20:50
  • 3
    @ChrisK How about something like this (untested)? http://pastebin.com/dVx0p2ph – Szabolcs Feb 22 '16 at 20:56
  • That works fine on my less minimal example. I'll try it on my real problem & report back. – Chris K Feb 22 '16 at 21:02
  • Works great on my real problem too and makes it much cleaner to look at. If you submit this as an answer I'd be happy to accept it. – Chris K Feb 22 '16 at 21:25
  • @ChrisK I'll submit tomorrow! :) – Szabolcs Feb 22 '16 at 22:29