5
$\begingroup$

Is it possible to detect (and create a trigger for) an event when any of the variables defined in the notebook changes its value (for any reason)?

I need to know which variable got changed and what the new value is.

Here are some details:

I have a client-server application, where the client is my Mathematica notebook. I also have a Java layer in between. The server runs MongoDB database and when any client modifies it, the server sends updates to all other clients. Specifically, to the Java layer. The job of the Java layer is to keep an up-to-date local copy of the database, and to relay all updates to the Mathematica client.


Needs["JLink`"]
InstallJava[];
ReinstallJava[ClassPath -> "/Users/verse/Desktop/java-ddp-client.jar"];
LoadJavaClass["java.lang.System"];
LoadJavaClass["java.lang.Object"];
LoadJavaClass["java.lang.reflect.Array"];
LoadJavaClass["com.wolfram.jlink.JLinkClassLoader"];
LoadJavaClass["me.kutrumbos.examples.MessageHandler"];

url = "localhost"; port = 3000; client = JavaNew["me.kutrumbos.DdpClient", url, MakeJavaObject[port]]; observer = JavaNew["me.kutrumbos.examples.ObservableDdpClientObserver"]; collections = {}; onCollectionUpdate[msg_] := Module[{}, collections = observer@getJSONObjectsList["test"];];

observer@addMessageHandler[ ImplementJavaInterface["me.kutrumbos.examples.MessageHandler", "update" -> "onCollectionUpdate"]];

client@addObserver[observer]; (ShowJavaConsole[];) client@connect[];

In this example, variable collections gets updated by the Java layer every time there is a change in the underlying database. It does not happen through the Set command inside the notebook. I need to know when this does happen and I need to properly update other variables.

Conversely, when any of the relevant variables change inside the notebook, I need to be able to update the database on the server using an API request. To send such a request, I need to know which variable has changed and what the new value is.

$\endgroup$
12
  • $\begingroup$ See the help for Dynamic there are many examples there. $\endgroup$
    – bill s
    Feb 7, 2014 at 15:59
  • $\begingroup$ have you seen Monitor[]? $\endgroup$ Feb 7, 2014 at 15:59
  • $\begingroup$ @bill s, would you mind pointing me to the part that you had in mind? I've read the Dynamic tutorial, but didn't see a way to detect the changes. My understanding was that Dynamic does the updating itself, but does not allow for trigger actions. @belisarius, I think Monitor won't work for my purposes -- it only shows the current value of a variable while a given expression is evaluated, but in my case there is no evaluation. Variables may be changed at any time by an external process (server update). $\endgroup$
    – verse
    Feb 7, 2014 at 16:08
  • 1
    $\begingroup$ Can you be clearer about what you want to happen? Present a specific scenario (preferably with code) so that we can see what you are trying to do? $\endgroup$
    – bill s
    Feb 7, 2014 at 16:15
  • $\begingroup$ @user6236 I have marked this question as too broad, because it is not clear what you are trying to do. Because of the way that Dynamic is implemented it may be useful or entirely useless for your task. There are other methods such as ScheduledTask that you should look at too. But outlining all of these methods is IMHO too extensive. $\endgroup$
    – Mr.Wizard
    Feb 7, 2014 at 16:31

2 Answers 2

4
$\begingroup$

Something along the lines of ...

a /: Set[a,x_]:=((OwnValues[a]={HoldPattern[a]:>x}; Print[{"a was set to:",x}]); a)

a = 1 prints {a was set to:,1}

a on its own is now 1.

Extends what set does with an additional action which here is Print but ,in principle, could be anything.

$\endgroup$
9
  • $\begingroup$ Be aware that this definition will not catch many of the ways that the value of a can change. I shall wait to see what the OP intends before voting on this. $\endgroup$
    – Mr.Wizard
    Feb 7, 2014 at 16:29
  • $\begingroup$ Unfortunately in my case this method won't work because the variables are updated by the Java layer, and not by the Set command. $\endgroup$
    – verse
    Feb 7, 2014 at 16:33
  • $\begingroup$ @user6236 I see the question has changed quite a bit since it was first posted. How soon after the collection has changed do you need to trigger your process? (emphasis on "need"). $\endgroup$
    – Ymareth
    Feb 7, 2014 at 16:43
  • $\begingroup$ @Ymareth I basically need to have consistently synchronized data across all clients and the server. This requires reacting to all the changes as quickly as possible. $\endgroup$
    – verse
    Feb 7, 2014 at 16:48
  • 1
    $\begingroup$ If anybody is willing to investigate or reverse engineer this, take a look at Internal`Handlers[], and see "ValueChange"-related ones are useful. I never dug into this and I don't even know if it works or not. $\endgroup$
    – Szabolcs
    Feb 7, 2014 at 19:36
9
$\begingroup$

There is ValueFunction, documented here.

It allows detecting value changes for given symbols.

For example,

In[1]:= Experimental`ValueFunction[x] := Print["x changed"]

In[2]:= x = 6

During evaluation of In[10]:= x changed

Out[2]= 6
$\endgroup$
9
  • 1
    $\begingroup$ Why doesn't this have any votes!? +1! $\endgroup$
    – Mr.Wizard
    May 11, 2014 at 17:49
  • $\begingroup$ From the docs: "ValueFunction takes account of all ways that the value of a symbol can be changed, not just Set." However, even a cursory examination shows that this is totally wrong. So much for "documentation"! $\endgroup$ May 11, 2014 at 20:09
  • $\begingroup$ @OleksandrR. How did you break it? $\endgroup$
    – Szabolcs
    May 11, 2014 at 21:51
  • $\begingroup$ Well, it failed with pretty much everything I tried. It seems only to pay attention to OwnValues. Yet, changing even these by any slightly non-standard method (e.g. manipulating OwnValues directly) doesn't trigger it. Nor does changing a part of a value. It would be interesting to know what scenarios it does actually cover. $\endgroup$ May 11, 2014 at 22:01
  • 1
    $\begingroup$ @Oleksandr I'm not surprised that direct modification of OwnValues doesn't work, at that is expressly outside of "normal" operation. Things like Increment and AppendTo do work, but I am sad to see that as you say assignments to parts do not. Nevertheless I think this still has value. $\endgroup$
    – Mr.Wizard
    May 12, 2014 at 16:20

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.