|
[Date Index]
[Thread Index]
[Author Index]
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
|