3
$\begingroup$

Motivation

I want to write an auxiliary function (brief auxf) for testing the output of another function that evaluates its body repeatedly using Pause in between evaluations.

This auxiliary function ideally must return a different value each time it is evaluated; those values need not be sequential but it's helpful if they are monotonic and deterministic.

The idea is to have a sense of what the output should be and juxtaposed it to the actual output of the function being tested in order to discern what branches get executed repeatedly etc.

Proposed approach

Now, what I could come up with was an auxf inspired by what I think generators are supposed to do in Python or what the iota operator does for Go constants.

Briefly, I figured that a function that increases its output value by a certain delta for every successive evaluation would be ideal for this type of situation.

After doing some (soul) searching I managed to combine this amazing post with that piece of info from the documentation (first example in the Applications section) to obtain counter (please note that auxf above and faux below are not related):

Module[{i = 0, reset, faux, invldoptval},
  reset[] := (i = 0;);
  counter::invldoptval = "Invalid option value '`1`'. Expected boolean.";
  Options[counter] = {"Reset" -> False};
  counter[args___] := faux[args];
  faux[args___, OptionsPattern[counter]] := Module[{resetQ = OptionValue["Reset"]},
     If[resetQ, reset[], i++, Message[counter::invldoptval, resetQ]]
   ]
 ]

Example

An example:

counter/@Range[5]
{0, 1, 2, 3, 4}

Resetting the counter:

counter["Reset"->True]
counter[]
counter[]
0
1

Evaluating counter with a wrong option value like in

 counter["Reset"->None]
 counter[]

produces a message

Invalid option value 'None'. Expected boolean.  
2

Question

  • Is there another idiomatic way to achieve a similar result as counter?
    • Are there any problems with this approach?
    • Can you think of other use cases for this piece of code?

Thanks!

$\endgroup$
  • 1
    $\begingroup$ How closely is this related: How to generate repeatable Unique streams?? Also, I'm not sure I understand how is the title related to questions at the bottom. $\endgroup$ – Kuba Jul 18 '18 at 9:00
  • $\begingroup$ I think the accepted answer to your link is an implementation of the link in the question (the former dates from '16 while the later dates from'12); as far as I can tell it is a simpler version of what counter does; the question is "is there better way to achieve the same effect that counter delivers?" (perhaps I should've incorporated 2 and 3 in 1); as far as the title is concerned would you be so kind as to explain on what level you experience the disconnect? I wasn't aware closures were possible in MA and what counter does is it "[...]create[s] closure" (link) $\endgroup$ – user42582 Jul 18 '18 at 12:56
  • 1
    $\begingroup$ I wrote a brief tutorial on using closures in Mathematica way back in 2011 in a personal blog. I find that basically no one uses them like this and very few people are even aware that Module preserves its private values in this way - even among pretty advanced users. I never thought to use Option in this way. That's really neat. I generally don't find it really useful to do this kind of stuff though. The internal state hurts referential transparency and is a bit heavy for lighter scripting. I've only really used this before in creating a logging tool that I only use for myself. $\endgroup$ – Searke Jul 18 '18 at 16:02
  • $\begingroup$ I understand the connection between counter and closure. I meant the whole title which is a question by itself and imo it is much broader to the question's content. I may be confused though. P.s. for other use of closures lookup Villegas-Gayley. $\endgroup$ – Kuba Jul 18 '18 at 19:28
  • $\begingroup$ @Kuba I'm by all means open to suggestions about the title and/or the q itself; the Villegas-Gayley trick seems really useful esp. for logging/testing purposes which I'm currently interested in; I'm struggling to see how it relates to counter though; hopefully after I digest UnevaluatedExpressions.nb I'll figure it out; thanks for the pointer it is really appreciated $\endgroup$ – user42582 Jul 24 '18 at 12:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.