# Defining local variables in a dynamic way in Module

I have a function whose variable are specified by a input parameters of function:

ParametersList1 = {{"a", 1}, {"b", 2}}
ParametersList2 = {{"a", 3}, {"b", 4}}

TestFunction[ParametersList_] := Module[{},
Table[ToExpression[ParametersList[[n]][[1]] <> "=" <> ToString[ParametersList[[n]][[2]]]],
{n, 1, Length[ParametersList]}];
Return[a + b]
]

TestFunction[ParametersList1]
3

TestFunction[ParametersList2]
6


The function works as expected, however, the parameter a and b should not be global. The number of parameters given by ParametersList is not known and I cannot explicitly describe it as Module[{a,b},...]. Is there anyway to define local variables in a dynamic way, for example, something like following?

Module[ToExpression[ParametersList[[All, 1]]],...]

• You could go with something like 783 but if you are using a or b explicitly too, you may end up with contex issues for more complicated cases. There are ways to deal with this too but if you are on v10+ then maybe vars = <|"a" -> 1, "b" -> 2|>; vars["a"] + vars["b"] instead of ParametersList1/2?
– Kuba
Mar 5, 2017 at 16:24
• a+b is rather complicated equation with many parameters and I would like to avoid adding vars[" "] for all of them.
– arb
Mar 5, 2017 at 16:34
• It seems from your code that you not only don't know the number of parameters but also not their names. So what use is it to assign values to some parameters of unknown names? You wouldn't be able to do a+b because you don't know that they are called a and b. Why then not just working with the list as it is? Return[Total[ParametersList[[All,2]]]] Mar 5, 2017 at 16:49
• Btw, how do you get 6 for TestFunction[ParametersList2]? Mar 5, 2017 at 16:50
• Could you provide a context, is this a tool for you to be used in a notebook or do you want to create a package for others, etc?
– Kuba
Mar 5, 2017 at 17:06

This is probably a duplicate of How to set Block local variables by code? or at least very similar.

Attributes[stringModule] = HoldRest;

stringModule[par : {{_String, _} ..}, body_] :=
Join @@ Cases[
MapAt[MakeExpression, par, {All, 1}],
{_[s_Symbol], v_} :> Hold[s = v]
] /. _[sets__] :> Module[{sets}, body]


Test:

a = b = "Failed!";

ParametersList1 = {{"a", 1}, {"b", 2}};
ParametersList2 = {{"a", 3}, {"b", 4}};

stringModule[ParametersList1, a + b]
stringModule[ParametersList2, a + b]

3

7


I use Cases and the pattern {_[s_Symbol], v_} :> Hold[s = v] to make sure that assignments are possible, so that malformed input is skipped, e.g.:

stringModule[{{"a", 3}, {"b", 4}, {"2c", 1}}, a + b + 2c]

7 + 2 c


2c is not a Symbol and therefore cannot be assigned so it is ignored.

Related:

• +1 though OP wanted to have a+b hardcoded, which is a bad idea and at the and we would end up with this solution anyway ;)
– Kuba
Mar 5, 2017 at 20:49
• Thank you, this is what I needed.
– arb
Mar 6, 2017 at 13:21
• @arb great, but it isn't what you asked for, your formulas are hardcoded inside your TestFunction and you only provide parameters. Please consider updating the question if that was not the main point.
– Kuba
Mar 6, 2017 at 13:34
• @Kuba I prefer hardcoded formula, but I am not sure if I insist on it, if it cannot be easily done. Is there any restriction on what formulas I could use in the parameter of stringModule[] function, compared with hardcoding it? I plan to use Mr.Wizard's suggestion as TestFunction[ParametersList_] := Module[{temp}, temp=stringModule[ParametersList1, a + b]; Return[temp] ] This seems to satisfy my needs.
– arb
Mar 6, 2017 at 14:28
• @arb I am glad I could help. If you find this answer fully satisfactory please consider Accepting it. Mar 6, 2017 at 20:30