In the tutorial Immutable Values "Gotcha", we stated that the value of a table is immutable once it is set. Specifically, this means you can not modify the value of one table from the formula of another. This is done so there are no side effects, so we can properly determine the order to calculate the tables.
However, there actually is a way to modify the value of one table from the formula of another table. And, this actually respects the requirement of no side effects, so that we can determine the proper order of calculation of the tables.
Before we talk about this, we will talk about how you modify the value of a table from outside the formula of a table. You use the keyboard. If we could not edit the workspace, you couldn't do anything with the application.
You edit a table by either entering a value explicitly or updating the formula. When you press save, Apogee recalculates the workspace. Given the fixed values or formulas for each table, it determines the proper order to evaluate all the formulas. It is during this calculation that there are no side effects.
If you then create another table or edit an existing table, once you press save the process will repeat. It is treated as an entirely new system and we recalculate the value of all the tables, again not allowing side effects during the calculation.
There is something called the messenger. You can access this from a formula for a table and use it to send a new value to another table. However, it doesn't change the value of the table right away. It waits until the current calculation is over. Then it sets the new value.
This is the same as if you decided to update the workspace yourself with a new value, just as we did in the above section Editing the Workspace. In fact, the two processes use the same code internally. As above, this does not violate the no side effect rule during a calculation.
Example workspace: Basic Usage Sample Workspace
Here we show the basic usage of the messenger from a formula. This example contains three tables (and the notes table):
valueToCopy - This holds a simple manually defined value.
test - This table has a formula that calls the messenger, and sends the value from valueToCopy to the table called remoteTable. It also returns a dummy value for its own value.
remoteTable - This table has no formula. It will receive its value from the messenger. To see this, update the value in the valueToCopy table.
Example workspace: User Input Sample Workspace
This example is one of the most common cases of using the messenger. It uses a control called a Dynamic Form Table, which is basically a customizable form that acts as a dialog box. There are other customizable forms too, such as ones that hold a value just like a data table. These form tables are introduced elsewhere.
From the userInputForm, view the code by selecting code from the View Dropdown in the top right corner. The code contains the layout of the form and, at the top, an onSubmitcallback function. From within this function, the messenger is accessed. It is used to send the value of the form to the table inputValue
To see this work, just enter data into the form and press OK.
Incidently, the code that defines the form layout for the userInputForm references the table inputValue, which is the table we write to when we press OK. If you update the data in the table inputValue manually, it will be reflected in the form. (But you might get an error. We didn't put much error checking in the form code.
Example workspace: Iterative Calculation Example Workspace
Generally in functional programming you must do recursive functions rather than iterative functions, which is OK. In Apogee, however, you can choose to do an iterative calculation, using the messenger. Sometimes it is more natural to do this, such as if you are simulating a feedback control system.
In this sample workspace, we calculate the factorial function iteratively. (Of course, this particular example is one that is very natural to do recursively, but we are just doing this an an example.)
This example contains four tables (and the notes table):
desiredN - This holds the value whose factorial you would like to calculate.
nMinus1Factorial - This should be initialized to some known factorial, such as 0!,where n=1.
n - This table should be initialized to the proper value of n associated with the nMinus1Factorial table.
nFactorial - This is the only table with a formula. It contains the simple formula n! = n * (n-1)! . In addition, it also uses the messenger to iterate the values of the nMinus1Factorial and n tables.
To try this out, update the value in the desiredN table. FYI, the largest factorial that can be calculated here is 171.
You may notice the calculation is very slow, so that you can actually see the values changing. The Apogee calculation itself is not that slow, however, the there is a lot of overhead with each iteration of the calculation, mainly from the UI. So, for now at least, doing a lot of iterations has a high performance cost. The messenger works best for things like the previous example, user input.