1
$\begingroup$

In the following I am using one function makeFunc to assemble two functions a[t] and b[t] to pass to use in the formation of a Table. makeFunc appears to be doing its job appropriately because the error messages and Trace show that it has assembled a[t] and that the Table construct has evaluated the t portion of the function. However, a[t] is not evaluating itself and so the Table appears as a[0], a[30], etc.

tempMakeTableAn[{analEqs_, concs_, initConcs_, rateConstants_, 
    timeDom_, timeInc_}] :=
  Module[{a, b},
   a[t_] := 
    aZero Exp[-k1 t] /. Evaluate[Join[initConcs, rateConstants]];
   b[t_] := 
    bZero + 1 - aZero a[t] /. Evaluate[Join[initConcs, rateConstants]];

   makeFunc[conc_, time_] := Evaluate[conc[time]];

   Column[{Table[{a[t], b[t]}, {t, 0, 300, 30}],
     Table[makeFunc[#, timeDom[[1]]] & /@ concs, {t, 0, 300, 30}]}]    
];

tempMakeTableAn[{{Hold[a[t_] := aZero Exp[-k1 t], 
    b[t_] := bZero + 1 - aZero a[t]]}, {a, b}, {aZero -> 1, 
   bZero -> 0}, {k1 -> .01}, {t, 0, 300}, {30}}]

{ {{{1, 0}, {0.740818, 0.259182}, {0.548812, 0.451188}, {0.40657, 0.59343}, {0.301194, 0.698806}, {0.22313, 0.77687}, {0.165299, 0.834701}, {0.122456, 0.877544}, {0.090718, 0.909282}, {0.0672055, 0.932794}, {0.0497871, 0.950213}}},

{{{a[0], b[0]}, {a[30], b[30]}, {a[60], b[60]}, {a[90], b[90]}, {a[120], b[120]}, {a[150], b[150]}, {a[180], b[180]}, {a[210], b[210]}, {a[240], b[240]}, {a[270], b[270]}, {a[300], b[300]}}} }

This appears to have something to do with the way that I am utilizing the Slot (#) as you can see that when I entered in a[t] and b[t] directly, the Table works.

I think that this may have to do with scoping of the variables, because if I remove a and b as declared variables in the Module, everything works as expected. I.e. a and b get defined globally and the expected Table appears.

I have also tried some judiciously placed Evaluate statements to see if that is what was needed, but that didn't make any changes.

I have found a couple of questions that I thought might be applicable (Using pure functions in Table,Evaluate[] seems to not work inside Button[]), but since the construct works when the variables are declared globally, I don't understand why it doesn't work when they are declared within the module.

Any help would be appreciated. [If somebody can come up with a better Title, have at it. This was the best that I could figure out].

$\endgroup$

2 Answers 2

2
$\begingroup$

You are seeing Module work exactly as it should, because it is designed to implement lexical scoping. Take it away, Wikipedia:

In lexical scoping (or lexical scope; also called static scoping or static scope), if a variable name's scope is a certain function, then its scope is the program text of the function definition: within that text, the variable name exists, and is bound to the variable's value, but outside that text, the variable name does not exist.

Thus, when you declare these symbols a and b at the top of your Module, Mathematica will create two new symbols (using Unique) and replace all occurrences of a and b within the Module's body with those new symbols. Look what happens when we have a Module that just returns the new symbols:

Module[{a, b}, {a, b}]
{a$1138, b$1138}

That's an example; the digits that come after the $ are appended by Mathematica to make the symbols unique. The same thing is happening in your first tempMakeTableAn function definition, so the as and bs appearing within the Module have nothing to do with the as and bs that are being defined/assigned in the second definition.

$\endgroup$
2
  • $\begingroup$ So that helps me understand what is going wrong, but is there a way I can force the second definition to not be a redefinition but use the Module's definition? $\endgroup$ Commented Apr 1, 2014 at 11:39
  • $\begingroup$ @rasher Rasher's comments to his answer above provided the fix that I needed. Thanks for your answer, it helped me understand the situation. $\endgroup$ Commented Apr 1, 2014 at 11:57
2
$\begingroup$

I think this does what you're trying to accomplish. Note, you're not using "pure functions" anywhere in your code, I just jiggered it to get what I think you're after, there are almost certainly cleaner ways to do what I think you're trying to do (like actually using pure functions, etc.)

tempMakeTableAn[{analEqs_, concs_, initConcs_, rateConstants_, 
    timeDom_, timeInc_}] := Module[{a, b},

   (ReleaseHold[analEqs /. Evaluate[Join[initConcs, rateConstants]]]);

   makeFunc[conc_, time_] := Evaluate[conc[time]];

   Table[makeFunc[#, timeDom[[1]]] & /@ concs, {t, 0, 300, 30}]];

tempMakeTableAn[{{Hold[a[t_] := aZero Exp[-k1 t]; 
    b[t_] := bZero + 1 - aZero a[t]]}, {a, b}, {aZero -> 1, 
   bZero -> 0}, {k1 -> .01}, {t, 0, 300}, {30}}]

(*
{{1., 0.}, {0.740818, 0.259182}, {0.548812, 0.451188}, {0.40657, 
  0.59343}, {0.301194, 0.698806}, {0.22313, 0.77687}, {0.165299, 
  0.834701}, {0.122456, 0.877544}, {0.090718, 0.909282}, {0.0672055, 
  0.932794}, {0.0497871, 0.950213}}
*)
$\endgroup$
5
  • $\begingroup$ I had used almost exactly the same construct. The problem is that the ReleaseHold defines a[t] and b[t] globally, and I want to avoid that (if I can). A related post to this problem is mathematica.stackexchange.com/questions/595/… and I tried to utilize that fix here, but did not manage it. For this reason, I had switched to defining them explicitly at the beginning in the Module. Thanks also for the correction on the use of the term "Pure Function". How can I better describe the use of the [#]&/. format? $\endgroup$ Commented Apr 1, 2014 at 11:36
  • $\begingroup$ Actually, if I could make what you answered work (with a and b being defined within the Module and not globally), that would be a much better solution for me. $\endgroup$ Commented Apr 1, 2014 at 11:41
  • $\begingroup$ @AndyMobley: change Module to Block, a/b will be local. $\endgroup$
    – ciao
    Commented Apr 1, 2014 at 11:42
  • $\begingroup$ That fixed it. Oh, I need to learn how to use Block. I'll start by re(re(re))reading mathematica.stackexchange.com/questions/559/… I actually marked it as my very first favorite when I first joined (not that long ago), but haven't learned the lessons yet. Thanks. Do you want to edit the answer to reflect the Block before I accept it? $\endgroup$ Commented Apr 1, 2014 at 11:56
  • $\begingroup$ AND . . . It appears that I can even define the declared variables in the Block on the fly by using the concs variable that came with the function. That is exactly what I wanted. $\endgroup$ Commented Apr 1, 2014 at 12:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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