MathGroup Archive 2010

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: looping

  • To: mathgroup at smc.vnet.net
  • Subject: [mg106861] Re: [mg106766] Re: [mg106704] looping
  • From: DrMajorBob <btreat1 at austin.rr.com>
  • Date: Mon, 25 Jan 2010 05:07:38 -0500 (EST)
  • References: <201001210955.EAA16523@smc.vnet.net>
  • Reply-to: drmajorbob at yahoo.com

Huh! That's an amazing little secret trick you have, there!

I wonder, though, if it could go away in a new version.

Bobby

On Sun, 24 Jan 2010 04:11:07 -0600, Leonid Shifrin <lshifr at gmail.com>  
wrote:

> Bobby,
>
> this is one of the nice (IMO) features of local variables in Module. By
> default, they have the attribute Temporary, which means that they are
> destroyed once the execution exits Module. However, if some global  
> symbols
> refer to them (like the functions you've mentioned), they are not  
> destroyed,
> but kept in a symbol table. I use this trick all the time - this allows  
> for
> example  to share local variables (and functions) between several  
> functions,
> which enables us to implement something similar to classes in OOP (If I
> remember corerctly, this idea has been fully exploited by Roman Maeder in
> his implementation of OOP in Mathematica - classes.m package).
>
> Have a look at my post in this thread, if you will
>
> http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/ec4958c35f99758d/
>
> there I implement the <pair> data type using this idea. In this thread:
>
> http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/4d566f1993c252c8/
>
> I used this trick to implement traversals of nested directory structure  
> with
> possible directory skips which can be set at run-time based on a skip
> function provided by the user.
>
> One of the many other ways to use this which I find useful is to  
> propagate
> exceptions of a given type without explicitly making the exception tag
> global. One particular such use I discussed in the thread:
>
> http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/bc41b4a5f51fbcb8/
>
> Generally, this is a good option when you  want to make an essentially
> global variable available to a given set of functions but not to others -
> you make it like
>
> Module[{youvar},
>
> f1[args]:=(body-referring-to-yourvar)
>
> f2[args]:=(body-referring-to-yourvar)
>
> ...
> ];
>
> This is a cheap way to introduce namespaces without making a full-blown
> package. This allows us to use some of the nice OOP-like stuff (such as
> private variables / methods) without the need to employ a general OOP
> machinery (that is, when we just need nice encapsulation but not so much
> OO-style polymorphism / inheritance). As long as the user never uses
> variables with a dollar sign in their names (which can possibly collide  
> with
> those generated by Module), this should be safe enough.
>
> One use of this is to make functions with "memory", similar to static  
> local
> variables in C functions - some of the function's variables remember  
> their
> values in between function calls. For example, the following function  
> will
> produce the next Fibonacci number on demand, and yet it will be as fast  
> as
> the iterative loop implementation for generation of consecutive Fibonacci
> numbers (since Module is invoked only once, when the function is  
> defined):
>
> In[1]:= Module[{prev, prevprev, this},
>   reset[] := (prev = 1; prevprev = 1);
>   reset[];
>   nextFib[] := (this = prev + prevprev; prevprev = prev; prev = this)];
>
>
> In[2]:=
> reset[];
> Table[nextFib[], {1000}]; // Timing
>
> Out[3]= {0.01, Null}
>
> In some cases, this can also improve performance, since some of the local
> variables in a function can be made "semi-global" by this trick which may
> eliminate the need of Module invocation in each function call, and the
> associated overhead:
>
> In[4]:=
> Clear[f, f1];
> f[x_, y_, z_] := Module[{xl = x, yl = y, zl = z}, (xl + yl + zl)^2];
>
> In[6]:=
> Module[{xl, yl, zl},
>   f1[x_, y_, z_] := (xl = x; yl = y; zl = z; (xl + yl + zl)^2)];
>
>
> In[8]:= test = RandomInteger[100, {10000, 3}];
>
> In[9]:= f @@@ test; // Timing
>
> Out[9]= {0.43, Null}
>
> In[10]:= f1 @@@ test; // Timing
>
> Out[10]= {0.15, Null}
>
>
> I generally find this technique very useful, and also I think that it has
> not been fully exploited (at least I did not fully exploit it yet). For
> example, you can do nice things when you couple it with Dynamic
> functionality, since Dynamic happens to work also on these  
> Module-generated
> variables.
>
> It may however have some garbage-collection issues (I discussed this in  
> the
> first of the threads I mentioned above), since once you abandon such  
> local
> variables/functions, they will not be automatically garbage-collected by
> Mathematica and can soak up memory (I have been bitten by this a few  
> times).
> Of course, this can be dealt with as well, it's just not automatic.
>
> Regards,
> Leonid
>
>
>
>
>
>
> On Sat, Jan 23, 2010 at 5:18 PM, DrMajorBob <btreat1 at austin.rr.com>  
> wrote:
>
>> Thanks! I've just noticed something I don't understand, however.
>>
>> How can displayPanel[] be used outside the makeScorePanel function,  
>> when it
>> uses studentInfo, text, buttons, and class -- all of which are local to  
>> the
>> Module??
>>
>> Bobby
>>
>>
>> On Sat, 23 Jan 2010 14:57:25 -0600, Leonid Shifrin <lshifr at gmail.com>
>> wrote:
>>
>>  Hi Bobby,
>>>
>>> I agree - your modification makes it more elegant. I  particularly  
>>> liked
>>> your  use of indexed variables and RandomChoice.
>>>
>>> Cheers,
>>> Leonid
>>>
>>>
>>> On Sat, Jan 23, 2010 at 12:48 PM, DrMajorBob <btreat1 at austin.rr.com>
>>> wrote:
>>>
>>>  I'd style this a bit differently:
>>>>
>>>> Clear[makeScorePanel];
>>>> makeScorePanel[names : {__String}] :=
>>>>  Module[{text, k = Length@names, name = RandomChoice@names,
>>>>   studentInfo, classFlag = True, buttons, class, percent, next,
>>>>   correct, questions},
>>>>
>>>>  "internal functions";
>>>>  correct[_] = 0; questions[_] = 0;
>>>>  percent[name_] /; questions[name] == 0 = 0;
>>>>  percent[name_] := Round[100*correct[name]/questions[name]];
>>>>
>>>>  "display elements";
>>>>
>>>>  text = "Was the answer correct?";
>>>>  next := (questions[name]++; name = RandomChoice@names);
>>>>
>>>>  class :=
>>>>   If[classFlag,
>>>>    Panel[Grid[
>>>>      Prepend[Transpose[{names, getQuestionCount[],
>>>>         getCorrectCount[], getPercent[]}], {"Name", "Questions",
>>>>        "# correct", "% correct"}], Spacings -> 3,
>>>>      Dividers -> Center]], ""];
>>>>  buttons :=
>>>>   Row[{Button["    Yes    ", correct[name]++; next],
>>>>     Button["    No    ", next],
>>>>     Button[If[classFlag, "Hide Roster", "Show Roster"],
>>>>      classFlag = ! classFlag]}];
>>>>  studentInfo :=
>>>>   Panel[
>>>>    Grid[{{"Name", name}, {"Questions",
>>>>       questions@name}, {"Correct answers",
>>>>       correct@name}, {"% correct", percent@name}},
>>>>     Alignment -> Left]];
>>>>
>>>>  "exported functions";
>>>>  Clear[getCorrectCount, getQuestionCount, getPercent,
>>>>   displayPanel];
>>>>  getCorrectCount[] := correct /@ names;
>>>>  getQuestionCount[] := questions /@ names;
>>>>  getPercent[] := percent /@ names;
>>>>  displayPanel[] :=
>>>>
>>>>   Dynamic@Panel[Column[{studentInfo, text, buttons, class}]]
>>>>  ];
>>>> makeScorePanel[{"apple", "bob", "cat", "dog", "ear", "frog", "greg",
>>>>  "hippo", "i9", "joe"}]
>>>> displayPanel[]
>>>>
>>>> Bobby
>>>>
>>>>
>>>> On Sat, 23 Jan 2010 06:30:56 -0600, Leonid Shifrin <lshifr at gmail.com>
>>>> wrote:
>>>>
>>>>  Hi Glenn,
>>>>
>>>>>
>>>>> You don't need a loop at all, if I understand your goal correctly.  
>>>>> What
>>>>> you
>>>>> need is a bit of Dynamic functionality. Hope this will get you  
>>>>> started:
>>>>>
>>>>> Clear[makeScorePanel, getScores, getCalled, getPrcntp, bpanel];
>>>>> makeScorePanel[names : {__String}] :=
>>>>>  Module[{text, n = RandomInteger[Length[names] - 1] + 1, studentInfo,
>>>>>   classFlag = False, buttons, class, percent, next,
>>>>>   score , called , prcnt},
>>>>>  Clear[getScores, getCalled, getPrcntp, bpanel];
>>>>>  score = called = prcnt = Table[0, {Length[names]}];
>>>>>  getScores[] := score;
>>>>>  getCalled[] := called;
>>>>>  getPrcntp[] := prcnt;
>>>>>  text := "Was the answer correct?";
>>>>>  next := (called[[n]]++; n = RandomInteger[Length[names] - 1] + 1);
>>>>>  class :=
>>>>>   If[classFlag,
>>>>>     Panel[Grid[
>>>>>      Transpose[{names, score,
>>>>>        IntegerPart[100*score/(called /. (0 -> 1))]/100.}
>>>>>       ],
>>>>>      Spacings -> 3, Dividers -> Center]],
>>>>>    ""];
>>>>>  buttons :=
>>>>>   Row[{
>>>>>     Button["    Yes    ", score[[n]]++; next],
>>>>>     Button["Class", classFlag = ! classFlag],
>>>>>     Button["    No    ", next]}];
>>>>>  percent :=
>>>>>   If[called[[n]] == 0, 0,
>>>>>    IntegerPart[100*score[[n]]/called[[n]]]/100.];
>>>>>  studentInfo :=
>>>>>   Panel[Grid[
>>>>>     {{"Name", names[[n]]},
>>>>>      {"Times called", called[[n]]},
>>>>>      {"# of correct answers", score[[n]]},
>>>>>      {"Your %     ", percent}},
>>>>>     Alignment -> Left]];
>>>>>  bpanel[] :=
>>>>>   Dynamic@Panel[Column[{
>>>>>       studentInfo,
>>>>>       text,
>>>>>       buttons,
>>>>>       class
>>>>>       }]]];
>>>>>
>>>>> The way to use: first call the makeScorePanel[] with your actual  
>>>>> list of
>>>>> names, then call bpanel[]:
>>>>>
>>>>> makeScorePanel[{"apple", "bob", "cat", "dog", "ear", "frog", "greg",
>>>>>  "hippo", "i9", "joe"}]
>>>>>
>>>>> bpanel[]
>>>>>
>>>>> You stop when you feel like it. You can also call   getScores[],
>>>>> getCalled[]
>>>>> ,  getPrcntp[] at any time to get the current state of these  
>>>>> variables
>>>>> (if
>>>>> you need that for further processing).
>>>>>
>>>>> Regards,
>>>>> Leonid
>>>>>
>>>>>
>>>>>
>>>>> On Thu, Jan 21, 2010 at 12:55 PM, glenn kuhaneck  
>>>>> <mcguyver128 at yahoo.com
>>>>> >wrote:
>>>>>
>>>>>  this code is supposed to randomly select a student from a list, keep
>>>>>
>>>>>> track
>>>>>> of how many times he/she has been called, and how many answers they
>>>>>> have
>>>>>> gotten correct.
>>>>>>
>>>>>> I am having problems getting the following code to repeat on  
>>>>>> request: i
>>>>>> have tried do loops, while loops, and labels none have worked.    
>>>>>> please
>>>>>> help
>>>>>>
>>>>>> These are the sample lists I am using for the code below
>>>>>> name = ( {
>>>>>>  {"apple"},
>>>>>>  {"bob"},
>>>>>>  {"cat"},
>>>>>>  {"dog"},
>>>>>>  {"ear"},
>>>>>>  {"frog"},
>>>>>>  {"greg"},
>>>>>>  {"hippo"},
>>>>>>  {"i9"},
>>>>>>  {"joe"}
>>>>>>  }); score = ({
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0}
>>>>>>  }); called = ({
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0}
>>>>>>  }); prcnt = ( {
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0},
>>>>>>  {0}
>>>>>>  } );
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> this is the code to manipulate the lists created above
>>>>>> repeat = "yes";
>>>>>> c = "wrong";
>>>>>> l = Length[name];
>>>>>> n = RandomInteger[l - 1] + 1;
>>>>>>
>>>>>>
>>>>>> Label[begin]
>>>>>> "Student #"
>>>>>> n
>>>>>> name[[n]]
>>>>>> called[[n]] += 1;
>>>>>> "# times called"
>>>>>> called
>>>>>> "Old Score"
>>>>>> score
>>>>>> Input["Was the answer correct?", Button["Yes", c = "Right"]];
>>>>>> If[c == "Right", score[[n]] += 1]; c
>>>>>> "New Score"
>>>>>> score
>>>>>> "Your # of Correct Answers"
>>>>>> score[[n]]
>>>>>> "Your %"
>>>>>> prcnt[[n]] = score[[n]]/called[[n]]
>>>>>> "Class %"
>>>>>> prcnt
>>>>>> Input["Another ?", Button["No", repeat = "no"]];
>>>>>> If[repeat == "yes", Goto[begin], Goto[end]];
>>>>>> Label[end];
>>>>>> prcnt[[n]]
>>>>>>
>>>>>>
>>>>>>
>>>>>> thank you for your assistance,
>>>>>>  Mr. Glenn J. Kuhaneck
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>> --
>>>> DrMajorBob at yahoo.com
>>>>
>>>>
>>
>> --
>> DrMajorBob at yahoo.com
>>


-- 
DrMajorBob at yahoo.com


  • References:
    • looping
      • From: glenn kuhaneck <mcguyver128@yahoo.com>
  • Prev by Date: Re: Re: Mathematica gets stuck,
  • Next by Date: Re: Re: looping
  • Previous by thread: Re: Re: Re: looping
  • Next by thread: Re: Re: looping