8
$\begingroup$

For teaching purposes, I want to create a Mathematica notebook that will "notice" when the user defines or redefines a variable or function of a particular name, so that it can check the value and take some appropriate action. For example, the notebook might be monitoring the symbol "foo", so that if the user executes foo = 22/7 at any time, code that I've written and hidden (perhaps in an invisible cell, perhaps via an initialization cell that loads a package I've written) might write out some hint text, e.g. "You've guessed the right variable name, but not the right value yet." I know I could do this by having the user click an explicit "test" button or some such thing, but I'd rather have my code monitor the user invisibly and take action without the user invoking it.

Is this possible? If so, how might it be implemented?

$\endgroup$
5
  • 3
    $\begingroup$ Have at look at $NewSymbol, etc. $\endgroup$
    – ciao
    Jul 4, 2015 at 20:24
  • $\begingroup$ That looks like it solves half my problem beautifully: Noticing when the symbol is created. Hm… Perhaps the function given to $NewSymbol can define a Dynamic[...] that will detect subsequent changes… $\endgroup$
    – ibeatty
    Jul 4, 2015 at 20:29
  • 2
    $\begingroup$ I think this is a bad idea for reasons that have nothing to do with Mathematica. If I were one of your students, I would be very disturbed when required to work with a notebook that appeared to contain a automaton that was watching my every move. The world does not need the Big Brother approach to teaching. On the hand, a palette with buttons such as "Check my answer" or "Give me a hint" would be acceptable because it would leave me feeling I was in control. Further, the palette approach would be much easier to implement and debug than the Big Brother approach. $\endgroup$
    – m_goldberg
    Jul 4, 2015 at 23:42
  • $\begingroup$ @m_goldberg: "You've guessed the right sentiment, but not the right values yet."... :-} $\endgroup$
    – ciao
    Jul 5, 2015 at 4:14
  • 1
    $\begingroup$ @m_goldberg: You're making assumptions about how I plan on using this. I'm planning a special-purpose notebook that acts somewhat like an interactive computer game or tutorial; students won't perceive this as Big Brother "watching" them, but rather the notebook interacting with them. (My profession is Physics Education Research. I know a thing or two about interacting constructively with students.) $\endgroup$
    – ibeatty
    Jul 7, 2015 at 15:17

2 Answers 2

7
$\begingroup$

Something, that more or less does what you asked for, can be achieved by creating a hidden InitializationCell using a DynamicWrapper

DynamicWrapper["xxx", 
 If[foo == 23, MessageDialog["You guessed it!"], 
  MessageDialog["You've guessed the right variable name, but not the right value yet."]]]

A much more elegant method is to use NotebookDynamicExpression:

SetOptions[EvaluationNotebook[], 
  NotebookDynamicExpression :> 
   Refresh[If[foo == 23, MessageDialog["You guessed it!"], 
     MessageDialog[
      "You've guessed the right variable name, but not the right value yet."]], 
    TrackedSymbols :> {foo}]];

You can remove this cell after evaluating it once, as the NotebookDynamicExpression is now part of the notebook.


Yet another possibility is to use ValueFunction in a hidden InitializationCell:

ValueFunction[foo] = 
  If[#2 == 23, MessageDialog["You guessed it!"], 
    MessageDialog[
     "You've guessed the right variable name, but not the right value yet."]] &;
$\endgroup$
1
  • $\begingroup$ This is an elegant way of monitoring one symbol! $\endgroup$
    – ibeatty
    Aug 8, 2015 at 16:48
3
$\begingroup$

One can use $Pre to check if an input expression defines the correct variable and is doing so using the correct value.

SetAttributes[check, HoldAll]
check[new_Set] := (Print["You guessed it!"]; new) /; HoldForm@new == HoldForm@Set[foo, 23]
check[new_Set] := (Print[
  "You've guessed the right variable name, but not the right value yet."]; new) /; 
 Extract[HoldForm[new], {1, 1}, Hold] == Hold[foo]
check[new_] := new
$Pre = check;

Example

$\endgroup$
1
  • $\begingroup$ It seems Mathematica has some very deep, powerful hooks like $Pre and $NewSymbol that I didn't know about. Thanks! $\endgroup$
    – ibeatty
    Jul 7, 2015 at 15:24

Your Answer

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

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